Micro ORM for C#
DataCore’s goal is to be a FOSS alternative to other ORMs. Focusing on simplicity and developer control over the queries and the database.
It uses Dapper for SQL execution and creates a layer on top of it to ease the query creation and database maintenance.
For now there’s no Nuget version, so you have to download/clone and build the current version from GitHub.
Each database has its own project. You can only add what you’ll use.
Each class represents one table and one table only.
Create a database for a connection using the desired provider and then you can use all methods from it.
class User
{
public int Id { get; set; }
public string Name { get; set; }
}
using (var db = new DataCoreDatabase(new SqliteDatabase(), "Data Source=:memory:"))
{
db.CreateTable<User>();
db.Insert(new User { Id = 1, Name = "Test User" });
var user = db.Select<User>(u => u.Id == 1);
}
db.Select<User>(u => u.Id == 1);
db.SelectSingle<User>(u => u.Id == 1);
db.SelectById<User>(1);
db.SelectById<User>(1, 2, 3);
You can use the Query class to create more complex queries.
var query = db.From<User>(); // creates query object
// create query using object
var result = db.Select(query); // executes the query
var result = db.Select<MaxUser>(query); // returning other class (when changing field names)
var query = db.From<User>().Join<Address>((u, a) => u.Id == a.UserId);
var result = db.Select(query);
var query = db.From<User>()
.LeftJoin<Address>((u, a) => u.Id == a.UserId)
.Where<Address>(a => a.Street.Like("Avenue%"));
var result = db.Select(query);
// note: not supported by SQLite
var query = db.From<User>().RightJoin<Address>((u, a) => u.Id == a.UserId);
var result = db.Select(query);
var query = db.From<User>().GroupBy(u => u.Name).Count();
var result = db.Select(query);
var query = db.From<User>().GroupBy(u => new { u.Name, u.Age }).Count();
var result = db.Select(query);
var query = db.From<User>().GroupBy(u => u.Name).Having(u => u.Age.Sum() > 100).Count();
var result = db.Select(query);
var query = db.From<User>()
.LeftJoin<Address>((u, a) => u.Id == a.UserId)
.GroupBy(u => u.Name)
.GroupBy<Address>(a => a.Street)
.Having(u => u.Age.Sum() > 100)
.Having<Address>(a => a.Sum.Number.Count() > 2)
.Count();
var result = db.Select(query);
var query = db.From<User>().Select(u => u.Id);
var result = db.Select(query);
var query = db.From<User>().Select(u => new { u.Id, u.Name });
var result = db.Select(query);
var query = db.From<User>().Select(u => new { u.Id, u.Name.Lower().As("Name") });
var result = db.Select(query);
var query = db.From<User>().Join<Address>((u, a) => u.Id == a.UserId)
.Select(u => u.Id).Select<Address>(a => a.Street);
var result = db.Select(query);
var query = database.From<User>().Where(u => u.Id == 1);
bool exists = database.Exists(query);
bool exists = database.Exists<User>(u => u.Id == 1);
You can use these extensions to use some SQL methods on your queries.
var query = db.From<User>().Select(u => u.Id.TrimSql());
var result = db.Select(query);
var result = db.Select<User>(u => u.Name.Like("%Test%"));
var query = db.From<User>().GroupBy(u => u.Age.IsNull(0)).Select(u => new { u.Age, u.Name.Length().Min().As("MinName") });
var result = db.Select(query);
Sum()
Min()
Max()
Average()
Count()
Between(start, end)
In(value1, value2, ...)
Like(string)
TrimSql()
Length()
Upper()
Lower()
IsNull(otherValue)
Cast<To>()
As(alias)
db.Insert<User>(new User { Id = 1, Name = "Test User" });
// updates user with Id = 1 with user data
db.Update<User>(user, u => u.Id == 1);
// only updates the name of the User with Id = 1
db.UpdateOnly<User>(user, t => t.Name, u => u.Id == 1);
// delete user with Id = 1
db.Delete<User>(u => u.Id == 1);
// delete user with Id = 1
db.DeleteById<User>(1);
// delete user with Ids 1, 2 and 3
db.DeleteById<User>(1, 2, 3);
You can use the following methods to create and drop parts of your database:
// databases (does not work for OracleDB)
db.CreateDatabase("test_db");
db.CreateDatabaseIfNotExists("test_db");
db.DatabaseExists("test_db"); // returns true
db.DropDatabaseIfExists("test_db");
db.DropDatabase("test_db");
// tables
db.CreateTable<User>();
db.CreateTables(typeof(User), typeof(Address));
db.CreateTableIfNotExists<User>();
db.CreateTablesIfNotExists(typeof(User), typeof(Address));
db.TableExists<User>(); // returns true
db.DropTable<User>();
db.DropTables(typeof(User), typeof(Address));
db.DropTableIfExists<User>();
db.DropTablesIfExists(typeof(User), typeof(Address));
db.DropAndCreateTable<User>();
db.DropAndCreateTables(typeof(User), typeof(Address));
// columns
db.CreateColumn<User>(t => t.NewColumn);
db.CreateColumnIfNotExists<User>(t => t.NewColumn);
db.ColumnExists<User>("NewColumn"); // returns true
db.ColumnExists<User>(t => t.NewColumn); // returns true
db.DropColumn<User>(t => t.NewColumn);
db.DropColumnIfExists<User>(t => t.NewColumn);
// indexes
db.CreateIndex<User>(t => new { t.Id, t.Name }, true, "IX_User_IdName_Unique");
db.CreateIndexIfNotExists<User>(t => new { t.Id, t.Name }, true, "IX_User_IdName_Unique");
db.IndexExists<User>("IX_User_IdName_Unique"); // returns true
db.IndexExists<User>(t => new { t.Id, t.Name }); // returns true
db.DropIndex<User>("IX_User_IdName_Unique");
db.DropIndexIfExists<User>("IX_User_IdName_Unique");
// foreign keys
db.CreateForeignKey<User, Address>(u => u.Id, a => a.UserId, "FK_User_Address");
db.CreateForeignKeyIfNotExists<User, Address>(u => u.Id, a => a.UserId, "FK_User_Address");
db.ForeignKeyExists<User>("FK_User_Address"); // returns true
db.ForeignKeyExists<User, Address>(u => u.Id, a => a.UserId); // returns true
db.DropForeignKey<User>("FK_User_Address");
db.DropForeignKeyIfExists<User>("FK_User_Address");
For automatic generation and Id usage, the following attributes can be used to decorate your properties.
[Table("USER")] // explicit table name
class User
{
// set as primary key, with the column name, and with AutoIncrement
[Column(isPrimaryKey: true, columnName: "User_ID"), Identity]
public int Id { get; set; }
// create an index when creating the table
[Index]
public string Login { get; set; }
public string Name { get; set; }
// set as nullable
[Column(isRequired: false)]
public DateTime InsertDate { get; set; }
// ignore the field for db
[Ignore]
public float Number { get; set; }
// create a foreign key to Address with the name provided
[Reference(typeof(Address), "FK_User_Address")]
public int AddressId { get; set; }
}
All push requests are welcome.
Aditional usages can be found in the test project.