Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 837283e

Browse files
committed
merge v5.5 release notes
1 parent 0fa96a8 commit 837283e

File tree

1 file changed

+190
-13
lines changed

1 file changed

+190
-13
lines changed

README.md

Lines changed: 190 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,18 @@ var q = db.From<Person>()
324324
Dictionary<int, List<string>> results = db.Lookup<int, string>(q);
325325
```
326326

327+
The new `db.KeyValuePair<K,V>` API is similar to `db.Dictionary<K,V>` where it uses the **first 2 columns** for its Key/Value Pairs to
328+
create a Dictionary but is more appropriate when the results can contain duplicate Keys or when ordering needs to be preserved:
329+
330+
```csharp
331+
var q = db.From<StatsLog>()
332+
.GroupBy(x => x.Name)
333+
.Select(x => new { x.Name, Count = Sql.Count("*") })
334+
.OrderByDescending("Count");
335+
336+
var results = db.KeyValuePairs<string, int>(q);
337+
```
338+
327339
### INSERT, UPDATE and DELETEs
328340

329341
To see the behaviour of the different APIs, all examples uses this simple model
@@ -1092,6 +1104,15 @@ using (var multi = db.QueryMultiple(q.ToSelectStatement()))
10921104
}
10931105
```
10941106

1107+
### SELECT DISTINCT in SelectMulti
1108+
1109+
[SelectMulti](https://github.com/ServiceStack/ServiceStack.OrmLite#selecting-multiple-columns-across-joined-tables) APIs for populating
1110+
multiple tables now supports **SELECT DISTINCT** with:
1111+
1112+
```csharp
1113+
var tuples = db.SelectMulti<Customer, CustomerAddress>(q.SelectDistinct());
1114+
```
1115+
10951116
### Select data from multiple tables into a Custom POCO
10961117

10971118
Another implicit behaviour when selecting from a typed SqlExpression is that results are mapped to the
@@ -1469,22 +1490,23 @@ var q = db.From<Table>()
14691490
.Select(x => x.Join1.Join2.IntValue);
14701491
```
14711492

1472-
### JOIN aliases
1493+
### Table aliases
14731494

1474-
You can specify join aliases when joining same table multiple times together to differentiate from any
1475-
ambiguous columns, e.g:
1495+
The `TableAlias` APIs lets you specify table aliases when joining same table multiple times together to differentiate from any
1496+
ambiguous columns in Queries with multiple self-reference joins, e.g:
14761497

14771498
```csharp
1478-
var q = db.From<Sale>()
1479-
.LeftJoin<ContactIssue>((s,c) => s.SellerId == c.Id, db.JoinAlias("seller"))
1480-
.LeftJoin<ContactIssue>((s,c) => s.BuyerId == c.Id, db.JoinAlias("buyer"))
1481-
.Select<Sale, ContactIssue>((s,c) => new {
1482-
s,
1483-
BuyerFirstName = Sql.JoinAlias(c.FirstName, "buyer"),
1484-
BuyerLastName = Sql.JoinAlias(c.LastName, "buyer"),
1485-
SellerFirstName = Sql.JoinAlias(c.FirstName, "seller"),
1486-
SellerLastName = Sql.JoinAlias(c.LastName, "seller"),
1499+
var q = db.From<Page>(db.TableAlias("p1"))
1500+
.Join<Page>((p1, p2) =>
1501+
p1.PageId == p2.PageId &&
1502+
p2.ActivityId == activityId, db.TableAlias("p2"))
1503+
.Join<Page,Category>((p2,c) => Sql.TableAlias(p2.Category) == c.Id)
1504+
.Join<Page,Page>((p1,p2) => Sql.TableAlias(p1.Rank,"p1") < Sql.TableAlias(p2.Rank,"p2"))
1505+
.Select<Page>(p => new {
1506+
ActivityId = Sql.TableAlias(p.ActivityId, "p2")
14871507
});
1508+
1509+
var rows = db.Select(q);
14881510
```
14891511

14901512
### Unique Constraints
@@ -1683,6 +1705,28 @@ SQLite offers [additional fine-grained behavior](https://sqlite.org/lang_conflic
16831705
- IGNORE
16841706
- REPLACE
16851707

1708+
### GetTableNames and GetTableNamesWithRowCounts APIs
1709+
1710+
As the queries for retrieving table names can vary amongst different RDBMS's, we've abstracted their implementations behind uniform APIs
1711+
where you can now get a list of table names and their row counts for all supported RDBMS's with:
1712+
1713+
```csharp
1714+
List<string> tableNames = db.GetTableNames();
1715+
1716+
List<KeyValuePair<string,long>> tableNamesWithRowCounts = db.GetTableNamesWithRowCounts();
1717+
```
1718+
1719+
> `*Async` variants also available
1720+
1721+
Both APIs can be called with an optional `schema` if you only want the tables for a specific schema.
1722+
It defaults to using the more efficient RDBMS APIs, which if offered typically returns an approximate estimate of rowcounts in each table.
1723+
1724+
If you need exact table row counts, you can specify `live:true`:
1725+
1726+
```csharp
1727+
var tablesWithRowCounts = db.GetTableNamesWithRowCounts(live:true);
1728+
```
1729+
16861730
### Modify Custom Schema
16871731

16881732
OrmLite provides Typed APIs for modifying Table Schemas that makes it easy to inspect the state of an
@@ -2951,7 +2995,7 @@ whilst the new `[SqlServerCollate]` attribute can be used to specify an SQL Serv
29512995

29522996
## PostgreSQL Features
29532997

2954-
### PostgreSQL Data Types
2998+
### PostgreSQL Rich Data Types
29552999

29563000
The `[PgSql*]` specific attributes lets you use attributes to define PostgreSQL rich data types, e.g:
29573001

@@ -2975,6 +3019,139 @@ public class MyPostgreSqlTable
29753019
}
29763020
```
29773021

3022+
By default all arrays of .NET's built-in **numeric**, **string** and **DateTime** types will be stored in PostgreSQL array types:
3023+
3024+
```csharp
3025+
public class Table
3026+
{
3027+
public Guid Id { get; set; }
3028+
3029+
public int[] Ints { get; set; }
3030+
public long[] Longs { get; set; }
3031+
public float[] Floats { get; set; }
3032+
public double[] Doubles { get; set; }
3033+
public decimal[] Decimals { get; set; }
3034+
public string[] Strings { get; set; }
3035+
public DateTime[] DateTimes { get; set; }
3036+
public DateTimeOffset[] DateTimeOffsets { get; set; }
3037+
}
3038+
```
3039+
3040+
You can opt-in to annotate other collections like `List<T>` to also be stored in array types by annotating them with `[Pgsql*]` attributes, e.g:
3041+
3042+
```csharp
3043+
public class Table
3044+
{
3045+
public Guid Id { get; set; }
3046+
3047+
[PgSqlIntArray]
3048+
public List<int> ListInts { get; set; }
3049+
[PgSqlBigIntArray]
3050+
public List<long> ListLongs { get; set; }
3051+
[PgSqlFloatArray]
3052+
public List<float> ListFloats { get; set; }
3053+
[PgSqlDoubleArray]
3054+
public List<double> ListDoubles { get; set; }
3055+
[PgSqlDecimalArray]
3056+
public List<decimal> ListDecimals { get; set; }
3057+
[PgSqlTextArray]
3058+
public List<string> ListStrings { get; set; }
3059+
[PgSqlTimestamp]
3060+
public List<DateTime> ListDateTimes { get; set; }
3061+
[PgSqlTimestampTz]
3062+
public List<DateTimeOffset> ListDateTimeOffsets { get; set; }
3063+
}
3064+
```
3065+
3066+
Alternatively if you **always** want `List<T>` stored in Array types, you can register them in the `PostgreSqlDialect.Provider`:
3067+
3068+
```csharp
3069+
PostgreSqlDialect.Provider.RegisterConverter<List<string>>(new PostgreSqlStringArrayConverter());
3070+
PostgreSqlDialect.Provider.RegisterConverter<List<int>>(new PostgreSqlIntArrayConverter());
3071+
PostgreSqlDialect.Provider.RegisterConverter<List<long>>(new PostgreSqlLongArrayConverter());
3072+
PostgreSqlDialect.Provider.RegisterConverter<List<float>>(new PostgreSqlFloatArrayConverter());
3073+
PostgreSqlDialect.Provider.RegisterConverter<List<double>>(new PostgreSqlDoubleArrayConverter());
3074+
PostgreSqlDialect.Provider.RegisterConverter<List<decimal>>(new PostgreSqlDecimalArrayConverter());
3075+
PostgreSqlDialect.Provider.RegisterConverter<List<DateTime>>(new PostgreSqlDateTimeTimeStampArrayConverter());
3076+
PostgreSqlDialect.Provider.RegisterConverter<List<DateTimeOffset>>(new PostgreSqlDateTimeOffsetTimeStampTzArrayConverter());
3077+
```
3078+
3079+
### Hstore support
3080+
3081+
To use `hstore`, its extension needs to be enabled in your PostgreSQL RDBMS by running:
3082+
3083+
CREATE EXTENSION hstore;
3084+
3085+
Which can then be enabled in OrmLite with:
3086+
3087+
```csharp
3088+
PostgreSqlDialect.Instance.UseHstore = true;
3089+
```
3090+
3091+
Where it will now store **string Dictionaries** in `Hstore` columns:
3092+
3093+
```csharp
3094+
public class TableHstore
3095+
{
3096+
public int Id { get; set; }
3097+
3098+
public Dictionary<string,string> Dictionary { get; set; }
3099+
public IDictionary<string,string> IDictionary { get; set; }
3100+
}
3101+
3102+
db.DropAndCreateTable<TableHstore>();
3103+
3104+
db.Insert(new TableHstore
3105+
{
3106+
Id = 1,
3107+
Dictionary = new Dictionary<string, string> { {"A", "1"} },
3108+
IDictionary = new Dictionary<string, string> { {"B", "2"} },
3109+
});
3110+
```
3111+
3112+
Where they can than be queried in postgres using [Hstore SQL Syntax](https://www.postgresql.org/docs/9.0/hstore.html):
3113+
3114+
```csharp
3115+
db.Single(db.From<PostgreSqlTypes>().Where("dictionary -> 'A' = '1'")).Id //= 1
3116+
```
3117+
3118+
Thanks to [@cthames](https://forums.servicestack.net/users/cthames/activity) for this feature.
3119+
3120+
### JSON data types
3121+
3122+
If you instead wanted to store arbitrary complex types in PostgreSQL's rich column types to enable deep querying in postgres,
3123+
you'd instead annotate them with `[PgSqlJson]` or `[PgSqlJsonB]`, e.g:
3124+
3125+
```csharp
3126+
public class TableJson
3127+
{
3128+
public int Id { get; set; }
3129+
3130+
[PgSqlJson]
3131+
public ComplexType ComplexTypeJson { get; set; }
3132+
3133+
[PgSqlJsonB]
3134+
public ComplexType ComplexTypeJsonb { get; set; }
3135+
}
3136+
3137+
db.Insert(new TableJson
3138+
{
3139+
Id = 1,
3140+
ComplexTypeJson = new ComplexType {
3141+
Id = 2, SubType = new SubType { Name = "JSON" }
3142+
},
3143+
ComplexTypeJsonb = new ComplexType {
3144+
Id = 3, SubType = new SubType { Name = "JSONB" }
3145+
},
3146+
});
3147+
```
3148+
3149+
Where they can then be queried on the server with [JSON SQL Syntax and functions](https://www.postgresql.org/docs/9.3/functions-json.html):
3150+
3151+
```csharp
3152+
var result = db.Single<TableJson>("table_json->'SubType'->>'Name' = 'JSON'");
3153+
```
3154+
29783155
# Limitations
29793156

29803157
### Single Primary Key

0 commit comments

Comments
 (0)