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

Commit 1df5fa4

Browse files
committed
Update README.md
1 parent 9e342c7 commit 1df5fa4

File tree

1 file changed

+175
-10
lines changed

1 file changed

+175
-10
lines changed

README.md

Lines changed: 175 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,51 @@ var track = db.SingleById<Track>(1);
866866
var tracks = db.SelectByIds<Track>(new[]{ 1,2,3 });
867867
```
868868

869+
### Ensure APIs
870+
871+
The new `Ensure()` API on OrmLite's typed `SqlExpression<T>` can be used to ensure that a condition is always applied irrespective
872+
of other conditions, e.g:
873+
874+
#### Typed API
875+
876+
```csharp
877+
var q = db.From<Rockstar>();
878+
q.Ensure(x => x.Id == 1); //always applied
879+
880+
//...
881+
q.Where(x => x.Age == 27);
882+
q.Or(x => x.LivingStatus == LivingStatus.Dead);
883+
884+
var rows = db.Select(q);
885+
```
886+
887+
#### Custom Parameterized SQL Expression
888+
889+
Custom SQL Ensure parameterized expressions:
890+
891+
```csharp
892+
q.Ensure("Id = {0}", 1);
893+
```
894+
895+
#### Multiple Ensure expressions
896+
897+
```csharp
898+
var q = db
899+
.From<Rockstar>()
900+
.Join<RockstarAlbum>((r,a) => r.Id == a.RockstarId);
901+
902+
q.Ensure<Rockstar,RockstarAlbum>((r,a) => a.Name == "Nevermind" && r.Id == a.RockstarId);
903+
904+
q.Where(x => x.Age == 27)
905+
.Or(x => x.LivingStatus == LivingStatus.Dead);
906+
907+
q.Ensure(x => x.Id == 3);
908+
909+
var rows = db.Select(q);
910+
```
911+
912+
These APIs are useful for mandatory filters like "Soft Deletes" and Multitenant records.
913+
869914
## Nested Typed Sub SqlExpressions
870915

871916
The `Sql.In()` API supports nesting and combining of multiple Typed SQL Expressions together
@@ -898,23 +943,39 @@ var names = new List<string>{ "foo", "bar", "qux" };
898943
var results = db.SqlList<Table>("SELECT * FROM Table WHERE Name IN (@names)", new { names });
899944
```
900945

946+
### Spread Util
947+
948+
The `SqlSpread()` API is useful to generate an escaped list of parameterized values for use in SQL `IN()` statements and SQL functions:
949+
950+
```csharp
951+
var dialect = db.Dialect();
952+
dialect.SqlSpread(1, 2, 3); //= 1,2,3
953+
dialect.SqlSpread("A", "B", "C"); //= 'A','B','C'
954+
dialect.SqlSpread("A'B", "C\"D"); //= 'A''B','C\"D'
955+
```
956+
901957
### Custom SQL using PostgreSQL Arrays
902958

903-
If using PostgreSQL you can take advantage of its complex Array Types and utilize its [Array Functions and Operators](https://www.postgresql.org/docs/9.6/functions-array.html), e.g:
959+
The `PgSql.Array()` provides a typed API for generating [PostgreSQL Array Expressions](https://www.postgresql.org/docs/current/arrays.html), e.g:
904960

905961
```csharp
906-
var ids = new[]{ 1, 2, 3};
907-
var q = Db.From<Table>()
908-
.Where("ARRAY[{0}] && ref_ids", ids.Join(","))
909-
var results = db.Select(q);
962+
PgSql.Array(1,2,3) //= ARRAY[1,2,3]
963+
var strings = new[]{ "A","B","C" };
964+
PgSql.Array(strings) //= ARRAY['A','B','C']
910965
```
911966

912-
When comparing a string collection you can use `SqlInValues` to create a quoted SQL IN list, e.g:
967+
Which you can safely use in Custom SQL Expressions that use PostgreSQL's native ARRAY support:
913968

914969
```csharp
915-
var q = Db.From<Table>()
916-
.Where($"ARRAY[{new SqlInValues(cities).ToSqlInString()}] && cities");
917-
var results = db.Select(q);
970+
q.And($"{PgSql.Array(anyTechnologyIds)} && technology_ids")
971+
q.And($"{PgSql.Array(labelSlugs)} && labels");
972+
```
973+
974+
If you want and empty collection to return `null` instead of an empty `ARRAY[]` you can use the `nullIfEmpty` overload:
975+
976+
```csharp
977+
PgSql.Array(new string[0], nullIfEmpty:true) //= null
978+
PgSql.Array(new[]{"A","B","C"}, nullIfEmpty:true) //= ARRAY['A','B','C']
918979
```
919980

920981
### Lazy Queries
@@ -972,7 +1033,7 @@ var q = db.From<Customer>()
9721033
var dbCustomers = db.Select<Customer>(q);
9731034
```
9741035

975-
This query rougly maps to the following SQL:
1036+
This query roughly maps to the following SQL:
9761037

9771038
```sql
9781039
SELECT Customer.*
@@ -1338,6 +1399,59 @@ Custom Key/Value Dictionary:
13381399
Dictionary<string,string> rows = db.Dictionary<string,string>(q);
13391400
```
13401401

1402+
### Dictionary APIs
1403+
1404+
OrmLite's Dictionary APIs allow you to customize which parts of a Data Model should be modified by
1405+
converting it into then manipulating an Object Dictionary, e.g:
1406+
1407+
#### Insert by Dictionary
1408+
1409+
```csharp
1410+
var row = new Person { FirstName = "John", LastName = "Smith" };
1411+
Dictionary<string,object> obj = row.ToObjectDictionary();
1412+
obj[nameof(Person.LastName)] = null;
1413+
1414+
row.Id = (int) db.Insert<Person>(obj, selectIdentity:true);
1415+
```
1416+
1417+
#### Update by Dictionary
1418+
1419+
```csharp
1420+
Person row = db.SingleById<Person>(row.Id);
1421+
var obj = row.ToObjectDictionary();
1422+
obj[nameof(Person.LastName)] = "Smith";
1423+
db.Update<Person>(obj);
1424+
```
1425+
1426+
#### UpdateOnly by Dictionary
1427+
1428+
```csharp
1429+
// By Primary Key Id
1430+
var fields = new Dictionary<string, object> {
1431+
[nameof(Person.Id)] = 1,
1432+
[nameof(Person.FirstName)] = "John",
1433+
[nameof(Person.LastName)] = null,
1434+
};
1435+
1436+
db.UpdateOnly<Person>(fields);
1437+
1438+
// By Custom Where Expression
1439+
var fields = new Dictionary<string, object> {
1440+
[nameof(Person.FirstName)] = "John",
1441+
[nameof(Person.LastName)] = null,
1442+
};
1443+
1444+
db.UpdateOnly<Person>(fields, p => p.LastName == "Hendrix");
1445+
```
1446+
1447+
#### Delete by Dictionary
1448+
1449+
```csharp
1450+
db.Delete<Rockstar>(new Dictionary<string, object> {
1451+
["Age"] = 27
1452+
});
1453+
```
1454+
13411455
### BelongsTo Attribute
13421456

13431457
The `[BelongTo]` attribute can be used for specifying how Custom POCO results are mapped when the resultset is ambiguous, e.g:
@@ -2247,6 +2361,41 @@ CREATE TABLE "PocoTable"
22472361

22482362
> OrmLite replaces any variable placeholders with the value in each RDBMS DialectProvider's `Variables` Dictionary.
22492363
2364+
### Custom Insert and Update Expressions
2365+
2366+
The `[CustomInsert]` and `[CustomUpdate]` attributes can be used to override what values rows are inserted during INSERT's and UPDATE's.
2367+
2368+
We can use this to insert a salted and hashed password using PostgreSQL native functions:
2369+
2370+
```csharp
2371+
public class CustomSqlUser
2372+
{
2373+
[AutoIncrement]
2374+
public int Id { get; set; }
2375+
2376+
public string Email { get; set; }
2377+
2378+
[CustomInsert("crypt({0}, gen_salt('bf'))"),
2379+
CustomUpdate("crypt({0}, gen_salt('bf'))")]
2380+
public string Password { get; set; }
2381+
}
2382+
2383+
var user = new CustomSqlUser {
2384+
Email = "[email protected]",
2385+
Password = "secret"
2386+
};
2387+
db.Insert(user);
2388+
```
2389+
2390+
We can then use `Sql.Custom()` to create a partially typed custom query to match on the hashed password, e.g:
2391+
2392+
```csharp
2393+
var quotedSecret = db.Dialect().GetQuotedValue("secret");
2394+
var q = db.From<CustomSqlUser>()
2395+
.Where(x => x.Password == Sql.Custom($"crypt({quotedSecret}, password)"));
2396+
var row = db.Single(q);
2397+
```
2398+
22502399
#### Pre / Post Custom SQL Hooks when Creating and Dropping tables
22512400

22522401
Pre / Post Custom SQL Hooks allow you to inject custom SQL before and after tables are created or dropped, e.g:
@@ -3155,6 +3304,22 @@ PostgreSqlDialect.Provider.RegisterConverter<List<DateTime>>(new PostgreSqlDateT
31553304
PostgreSqlDialect.Provider.RegisterConverter<List<DateTimeOffset>>(new PostgreSqlDateTimeOffsetTimeStampTzArrayConverter());
31563305
```
31573306

3307+
### PostgreSQL Params
3308+
3309+
The `PgSql.Param()` API provides a resolve the correct populated `NpgsqlParameter` and `NpgsqlDbType` from a C# Type
3310+
which can be used to query custom PostgreSQL Data Types in APIs that accept `IDbDataParameter` parameters, e.g:
3311+
3312+
```csharp
3313+
public class FunctionResult
3314+
{
3315+
public int[] Val { get; set; }
3316+
}
3317+
3318+
var p = PgSql.Param("paramValue", testVal);
3319+
var sql = "SELECT * FROM my_func(@paramValue)";
3320+
var rows = db.Select<FunctionResult>(sql, new [] { p });
3321+
```
3322+
31583323
### Hstore support
31593324

31603325
To use `hstore`, its extension needs to be enabled in your PostgreSQL RDBMS by running:

0 commit comments

Comments
 (0)