Skip to content

Commit 6845da5

Browse files
committed
Merge branch 'develop' into master
2 parents fc9b649 + c777345 commit 6845da5

File tree

123 files changed

+8309
-7553
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+8309
-7553
lines changed

.github/FUNDING.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# These are supported funding model platforms
2+
3+
github: [vdaron]
4+
patreon: # Replace with a single Patreon username
5+
open_collective: # Replace with a single Open Collective username
6+
ko_fi: # Replace with a single Ko-fi username
7+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9+
liberapay: # Replace with a single Liberapay username
10+
issuehunt: # Replace with a single IssueHunt username
11+
otechie: # Replace with a single Otechie username
12+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

README.md

Lines changed: 52 additions & 231 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,29 @@
1-
# A Dapper based ORM for .NET
1+
# SimpleStack.Orm
22

3-
## Introduction
3+
[![Build Status](https://img.shields.io/nuget/dt/simplestack.orm)](https://www.nuget.org/packages/SimpleStack.Orm)
4+
[![Build Status](https://img.shields.io/github/license/simplestack/simplestack.orm)](https://www.github.com/simplestack/simplestack.orm)
5+
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/simplestack/simplestack.orm)](https://github.com/SimpleStack/simplestack.orm/releases/)
6+
![GitHub top language](https://img.shields.io/github/languages/top/simplestack/simplestack.orm)
7+
![Maintenance](https://img.shields.io/maintenance/yes/2020)
8+
[![Twitter URL](https://img.shields.io/twitter/url?label=Follow%20us&style=social&url=https%3A%2F%2Ftwitter.com%2Fsimplestackproj)](https://twitter.com/simplestackproj)
49

5-
Follow [@simplestackproj](http://twitter.com/simplestackproj) on twitter for updates.
10+
[SimpleStack.Orm](https://simplestack.org) is a layer on top of the wonderful [Dapper](https://github.com/StackExchange/dapper-dot-net/) project that generate SQL queries based on lambda expressions. It is designed to persist types with a minimal amount of intrusion and configuration. All the generated sql queries are using parameters to improve performance and security.
11+
12+
By using Dynamic queries it is also possible to generate queries without a corresponding Type, see [Dynamic Queries](https://simplestack.org/query/select_async_dyn) for more information.
613

7-
SimpleStack.Orm is a set of light-weight C# extension methods around `System.Data.*` interfaces which is designed to persist POCO classes with a minimal amount of intrusion and configuration.
14+
#### Main goals:
815

9-
SimpleStack.Orm is based on the wonderfull [Dapper](https://github.com/StackExchange/dapper-dot-net/) project for all database acces. The SQL query generation code is based on [NServiceKit.OrmLite](https://github.com/NServiceKit/NServiceKit.OrmLite)
16+
* Map a Type 1:1 to an RDBMS table or view.
17+
* Create/Drop DB Table schemas using nothing but a Type. (IOTW a true code-first ORM)
18+
* Simplicity - typed, wrist friendly API for common data access patterns.
19+
* Full use of query parameters.
20+
* Supports multiple databases. Currently: Sql Server, Sqlite, MySql, PostgreSQL)
21+
* Cross Platform, based on netstandard 2.0.
22+
* Support connections on multiple databases from the same application
23+
24+
In SimpleStak.Orm : **1 Class = 1 Table/View**. There are no surprising or hidden behavior. [Attributes](https://simplestack.org/attributes) may be added on your Type to tune the queries generation (Alias, Schema, PrimaryKey, Index,...)
1025

11-
Main objectives:
12-
13-
* Map a POCO class 1:1 to an RDBMS table, cleanly by conventions, without any attributes required.
14-
* Create/Drop DB Table schemas using nothing but POCO class definitions (IOTW a true code-first ORM)
15-
* Simplicity - typed, wrist friendly API for common data access patterns.
16-
* Fully parameterized queries
17-
* Cross platform - supports multiple dbs (currently: Sql Server, Sqlite, MySql, PostgreSQL) running on both .NET and Mono platforms.
18-
19-
In SimpleStak.Orm : **1 Class = 1 Table**. There should be no surprising or hidden behaviour.
20-
21-
Effectively this allows you to create a table from any POCO type and it should persist as expected in a DB Table with columns for each of the classes 1st level public properties.
22-
23-
# Install
24-
25-
## Depending on the database you want to target:
26-
27-
- [Sql Server](https://www.nuget.org/packages/SimpleStack.Orm.SqlServer)
28-
- [MySql](https://www.nuget.org/packages/SimpleStack.Orm.MySQL)
29-
- [PostgreSQL](https://www.nuget.org/packages/SimpleStack.Orm.PostgreSQL)
30-
- [Sqlite](https://www.nuget.org/packages/SimpleStack.Orm.Sqlite/)
31-
32-
### 2 minutes sample
26+
### Sample usage
3327

3428
```csharp
3529
using SimpleStack.Orm;
@@ -39,10 +33,13 @@ namespace Test{
3933

4034
public class sample{
4135

36+
[Alias("dogs")]
4237
public class Dog{
43-
[PrimaryKey]
38+
[PrimaryKey()]
39+
[AutoIncrement()]
4440
public int Id{get; set;}
4541
public string Name{get; set;}
42+
[Alias("birth_date")]
4643
public DateTime? BirthDate{get; set;}
4744
public decimal Weight{get; set;}
4845
public string Breed{get; set;}
@@ -53,218 +50,42 @@ namespace Test{
5350
{
5451
conn.CreateTable<Dog>();
5552

53+
// INSERT INTO "dogs" ("Id", "Name", "birth_date", "Weight", "Breed" ) VALUES (@p_0, @p_1, @p_2, @p_3, @p_4)
5654
conn.Insert(new Dog{Name="Snoopy", BirthDate = new DateTime(1950,10,01), Weight=25.4});
5755
conn.Insert(new Dog{Name="Rex", Weight=45.6});
58-
conn.Insert(new Dog{Name="Rintintin", BirthDate = new DateTime(1918,09,13), Weight=2});
56+
conn.Insert(new Dog{Name="Popol", BirthDate = new DateTime(1918,09,13), Weight=2});
5957

58+
// SELECT "Id", "Name", "birth_date" AS BirthDate, "Weight", "Breed"
59+
// FROM "dogs"
60+
// WHERE ("Id" = @p_0)
61+
// ORDER BY 1 -- ORDER BY is mandatory to use OFFSET and FETCH clause in SQLServer
62+
// OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
6063
var rex = conn.First<Dog>(x => Id == 2);
64+
6165
rex.BirthDate = new DateTime(1994,11,10);
6266

67+
// UPDATE "dogs" SET "Name"=@p_0, "birth_date"=@p_1, "Weight"=@p_2, "Breed"=@p_3 WHERE "Id"=@p_4
6368
conn.Update(rex);
6469

65-
conn.Delete<Dog>(x => x.Name == "Rintintin");
70+
// DELETE FROM "dogs" WHERE ("Name" = @p_0)
71+
conn.DeleteAll<Dog>(x => x.Name == "Popol");
72+
73+
// SELECT "Name", "Breed", "Weight"
74+
// FROM "dogsbackup"
75+
// WHERE (DATEPART(year,"birth_date") = @p_0) --will be specific depending on database
76+
// ORDER BY "Breed" ASC,"Weight" DESC
77+
conn.Select<Dog>(x => {
78+
x.From("dogsbackup"); // Change From clause
79+
x.Select(y => new {y.Name,y.Breed,y.Weight}); // Only return some fields
80+
x.Where(y => y.BirthDate.Value.Year == 2019);
81+
x.OrderBy(y => y.Breed)
82+
.ThenByDescending(y => y.Weight);
83+
});
84+
85+
// SELECT AVG(Weight) AS Weight
86+
// FROM "dogs"
87+
conn.GetScalar<Dog, decimal>(x => Sql.Avg(x.Weight))
6688
}
6789
}
6890
}
6991
```
70-
71-
## 20 Minutes sample
72-
73-
As SimpleStack.Orm is based on Dapper, I encourage you to have a look at [Dapper documentation](https://github.com/StackExchange/dapper-dot-net/blob/master/Readme.md).
74-
75-
The first thing todo is to create an OrmConnectionFactory specifying the Dialectprovider to use and the connectionstring of your database.
76-
77-
```csharp
78-
79-
var factory = new OrmConnectionFactory(new SqlServerDialectProvider(), "server=...");
80-
using (var conn = factory.OpenConnection())
81-
{
82-
//TODO use connection
83-
}
84-
```
85-
86-
The DialectProvider contains all the specific code required for each database.
87-
88-
## WHERE clause generation using strong type LINQ queries
89-
90-
### Equals, Not equals, Bigger than, Less than, Contains,...
91-
92-
```csharp
93-
db.Select<Dog>(q => q.Name == "Rex"); // WHERE ("Name" = 'Rex')
94-
db.Select<Dog>(q => q.Name != "Rex"); // WHERE ("Name" <> 'Rex')
95-
db.Select<Dog>(q => q.Weight == 10); // WHERE ("Weight" = 10)
96-
db.Select<Dog>(q => q.Weight > 10); // WHERE ("Weight" > 10)
97-
db.Select<Dog>(q => q.Weight >= 10); // WHERE ("Weight" >= 10)
98-
db.Select<Dog>(q => q.Weight < 10); // WHERE ("Weight" < 10)
99-
db.Select<Dog>(q => q.Weight <= 10); // WHERE ("Weight" <= 10)
100-
db.Select<Dog>(q => q.Name.Contains("R")); // WHERE ("Name" LIKE("%R%"))
101-
db.Select<Dog>(q => q.Name.StartWith("R")); // WHERE ("Name" LIKE("R%"))
102-
db.Select<Dog>(q => q.Name.EndWidth("R")); // WHERE ("Name" LIKE("%R"))
103-
104-
```
105-
106-
### Combine criterias with AND or OR
107-
108-
```csharp
109-
// WHERE ("Name" LIKE 'R' OR "Weight" > 10)
110-
db.Select<Dog>(q => q.Name.Contains("R") || q.Weight > 10);
111-
// WHERE ("Name" LIKE 'R' AND "Weight" > 10)
112-
db.Select<Dog>(q => q.Name.Contains("R") && q.Weight > 10);
113-
```
114-
115-
### Sql class
116-
117-
#### IN Criteria
118-
119-
```csharp
120-
// WHERE "Breed" In ('Beagle', 'Border Collie', 'Golden Retriever')
121-
db.Select<Dog>(q => Sql.In(q.Breed, "Beagle", "Border Collie", "Golden Retriever"));
122-
```
123-
124-
#### Date part methods
125-
Use the date function (specific for each database)
126-
```csharp
127-
// SELECT YEAR("BirthDate") FROM DOG
128-
conn.GetScalar<Dog, int>(x => Sql.Year(x.BirthDate))
129-
// OR
130-
conn.GetScalar<Dog, int>(x => x.BirthDate.Year)
131-
132-
// SELECT "Id","Name","Breed","DareBirth","Weight" FROM DOG WHERE MONTH("BirthDate") = 10
133-
conn.Select<Dog>(x => Sql.Month(x.BirthDate) = 10)
134-
// OR
135-
conn.Select<Dog>(x => x.BirthDate.Month = 10)
136-
```
137-
138-
#### Aggregation function
139-
140-
```csharp
141-
// SELECT MAX("BirthDate") FROM DOG
142-
conn.GetScalar<Dog, DateTime>(x => Sql.Max(x.BirthDate))
143-
// SELECT AVG("Weight") FROM DOG
144-
conn.GetScalar<Dog, decimal>(x => Sql.Avg(x.Weight))
145-
```
146-
147-
148-
## INSERT, UPDATE and DELETEs
149-
150-
To see the behaviour of the different APIs, all sample uses this simple model
151-
152-
```csharp
153-
public class Person
154-
{
155-
public int Id { get; set; }
156-
public string FirstName { get; set; }
157-
public string LastName { get; set; }
158-
public int? Age { get; set; }
159-
}
160-
```
161-
162-
### Update
163-
164-
The "Update" method will always update up to one row by generating the where clause using PrimaryKey definitions
165-
166-
```csharp
167-
//UPDATE "Person" SET "FirstName" = 'Jimi',"LastName" = 'Hendrix',"Age" = 27 WHERE "Id" = 1
168-
db.Update(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix", Age = 27});
169-
```
170-
171-
To update only some columns, you can use the "onlyField" parameter
172-
173-
```csharp
174-
//UPDATE "Person" SET "Age" = 27 WHERE "Id" = 1
175-
db.Update(new Person { Id = 1, Age = 27}, x => x.Age);
176-
//UPDATE "Person" SET "LastName" = 'Hendrix',"Age" = 27 WHERE "Id" = 1
177-
db.Update(new Person { Id = 1, LastName = "Hendrix", Age = 27}, x => new {x.Age, x.LastName});
178-
```
179-
180-
Anonymous object can also be used
181-
182-
```csharp
183-
//UPDATE "Person" SET "Age" = 27 WHERE "Id" = 1
184-
db.Update<Person>(new { Id = 1, Age = 27}, x => x.Age);
185-
//UPDATE "Person" SET "LastName" = 'Hendrix',"Age" = 27 WHERE "Id" = 1
186-
db.Update<Person>(new { Id = 1, LastName = "Hendrix", Age = 27}, x => new {x.Age, x.LastName});
187-
```
188-
189-
### UpdateAll
190-
191-
The "UpdateAll" method will update rows using the specified where clause (if any).
192-
193-
```csharp
194-
//UPDATE "Person" SET "FirstName" = 'JJ'
195-
db.UpdateAll(new Person { FirstName = "JJ" }, p => p.FirstName);
196-
//UPDATE "Person" SET "FirstName" = 'JJ' WHERE AGE > 27
197-
db.UpdateAll(new Person { FirstName = "JJ" }, p => p.FirstName, x => x.Age > 27);
198-
```
199-
200-
### INSERT
201-
202-
#### Insert a single row
203-
204-
```csharp
205-
//INSERT INTO "Person" ("Id","FirstName","LastName","Age") VALUES (1,'Jimi','Hendrix',27)
206-
db.Insert(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix", Age = 27 });
207-
```
208-
209-
#### Insert multiple rows
210-
211-
```csharp
212-
//INSERT INTO "Person" ("Id","FirstName","LastName","Age") VALUES (1,'Jimi','Hendrix',27)
213-
db.Insert(new []{
214-
new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix", Age = 27 },
215-
new Person { Id = 2, FirstName = "Kurt", LastName = "Cobain", Age = 27 },
216-
});
217-
```
218-
219-
#### AutoIncremented Primary Keys
220-
221-
if you specify a PrimaryKey as AutoIncrement, the PrimaryKey is not added in the INSERT query
222-
223-
```csharp
224-
public class Person
225-
{
226-
[PrimaryKey]
227-
[AutoIncrement]
228-
public int Id { get; set; }
229-
public string FirstName { get; set; }
230-
public string LastName { get; set; }
231-
public int? Age { get; set; }
232-
}
233-
234-
//INSERT INTO "Person" ("FirstName","LastName","Age") VALUES ('Jimi','Hendrix',27)
235-
db.Insert(new Person { FirstName = "Jimi", LastName = "Hendrix", Age = 27 });
236-
237-
```
238-
239-
### Delete
240-
241-
The "Delete" method will always delete up to one row by generating the where clause using PrimaryKey definitions
242-
243-
```csharp
244-
//DELETE FROM "Person" WHERE ("Id" = 2)
245-
db.Delete(new Person{Id = 2});
246-
```
247-
248-
### DeleteAll
249-
Or an Expression Visitor:
250-
```csharp
251-
//DELETE FROM "Person" WHERE ("Age" = 27)
252-
db.DeleteAll<Person>(x => x.Age = 27);
253-
```
254-
255-
### Primary Keys, Foreign keys and Indexes
256-
257-
TODO
258-
259-
### Available Attributes
260-
261-
TODO
262-
263-
### Select using JOINs
264-
265-
TODO
266-
267-
### TypeMappers
268-
269-
TODO
270-

SimpleStack.Orm.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleStack.Orm.SQLite", "s
2626
EndProject
2727
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleStack.Orm.MySQLConnector", "src\SimpleStack.Orm.MySQLConnector\SimpleStack.Orm.MySQLConnector.csproj", "{75E2C0D4-FE33-484F-8EC1-58EA1EBFEBE0}"
2828
EndProject
29-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStack.Orm.SDSQlite", "src\SimpleStack.Orm.SDSQlite\SimpleStack.Orm.SDSQlite.csproj", "{49DB362E-E574-4BF2-A4D2-76CAD8EA6E85}"
29+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStack.Orm.SDSQLite", "src\SimpleStack.Orm.SDSQLite\SimpleStack.Orm.SDSQLite.csproj", "{49DB362E-E574-4BF2-A4D2-76CAD8EA6E85}"
3030
EndProject
3131
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStack.Orm.xUnit", "test\SimpleStack.Orm.xUnit\SimpleStack.Orm.xUnit.csproj", "{41DD3284-5112-4A27-AE18-09493B040031}"
3232
EndProject
33+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleStack.Orm.Logging.MicrosoftExtensions", "src\SimpleStack.Orm.Logging.MicrosoftExtensions\SimpleStack.Orm.Logging.MicrosoftExtensions.csproj", "{FA11989E-8998-40E3-B9D7-7925D8EBF7D0}"
34+
EndProject
3335
Global
3436
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3537
Debug|Any CPU = Debug|Any CPU
@@ -72,6 +74,10 @@ Global
7274
{41DD3284-5112-4A27-AE18-09493B040031}.Debug|Any CPU.Build.0 = Debug|Any CPU
7375
{41DD3284-5112-4A27-AE18-09493B040031}.Release|Any CPU.ActiveCfg = Release|Any CPU
7476
{41DD3284-5112-4A27-AE18-09493B040031}.Release|Any CPU.Build.0 = Release|Any CPU
77+
{FA11989E-8998-40E3-B9D7-7925D8EBF7D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
78+
{FA11989E-8998-40E3-B9D7-7925D8EBF7D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
79+
{FA11989E-8998-40E3-B9D7-7925D8EBF7D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
80+
{FA11989E-8998-40E3-B9D7-7925D8EBF7D0}.Release|Any CPU.Build.0 = Release|Any CPU
7581
EndGlobalSection
7682
GlobalSection(SolutionProperties) = preSolution
7783
HideSolutionNode = FALSE
@@ -86,6 +92,7 @@ Global
8692
{75E2C0D4-FE33-484F-8EC1-58EA1EBFEBE0} = {6EAAA3BA-9C88-4F21-A822-F0A3A9613EBA}
8793
{49DB362E-E574-4BF2-A4D2-76CAD8EA6E85} = {6EAAA3BA-9C88-4F21-A822-F0A3A9613EBA}
8894
{41DD3284-5112-4A27-AE18-09493B040031} = {DBBF1C8A-4A4B-4EC5-911C-BA6AEAC12BD4}
95+
{FA11989E-8998-40E3-B9D7-7925D8EBF7D0} = {6EAAA3BA-9C88-4F21-A822-F0A3A9613EBA}
8996
EndGlobalSection
9097
GlobalSection(ExtensibilityGlobals) = postSolution
9198
SolutionGuid = {82883C1A-728B-43E5-A494-6BA0585C069B}

0 commit comments

Comments
 (0)