中文 | English
Preface
I have tried ADO.NET, Dapper, EF, and Repository storage, and even wrote a generator tool myself to do common CRUD operations.
Their operation is inconvenient:
-
Need to declare before use;
-
Each entity class corresponds to an operation class (or DAL, DbContext, Repository).
BaseEntity is a very simple way of CodeFirst development, especially for single-table or multi-table CRUD operations. BaseEntity uses "inheritance" to save the repetitive code (creation time, ID and other fields) and functions of each entity class, and at the same time, it is not necessary to consider the use of repository when performing CURD operations.
This article will introduce a very simple CRUD operation method of BaseEntity.
Features
-
Automatically migrate the entity structure (CodeFirst) to the database;
-
Directly perform CRUD operations on entities;
-
Simplify user-defined entity types, eliminating hard-coded primary keys, common fields and their configuration (such as CreateTime, UpdateTime);
-
Logic delete of single-table and multi-table query;
Declaring
dotnet add package FreeSql.Extensions.BaseEntity
dotnet add package FreeSql.Provider.Sqlite
BaseEntity.Initialization(fsql, null);
- Define an auto-increment primary key of type
int
. When theTKey
ofBaseEntity
is specified asint/long
, the primary key will be considered as auto-increment;
public class UserGroup : BaseEntity<UserGroup, int>
{
public string GroupName { get; set; }
}
If you don't want the primary key to be an auto-increment key, you can override the attribute:
public class UserGroup : BaseEntity<UserGroup, int>
{
[Column(IsIdentity = false)]
public override int Id { get; set; }
public string GroupName { get; set; }
}
For more information about the attributes of entities, please refer to: https://github.com/dotnetcore/FreeSql/wiki/Entity-Attributes
- Define an entity whose primary key is Guid type, when saving data, it will automatically generate ordered and non-repeated Guid values (you don't need to specify
Guid.NewGuid()
yourself);
public class User : BaseEntity<UserGroup, Guid>
{
public string UserName { get; set; }
}
Usage of CRUD
//Insert Data
var item = new UserGroup { GroupName = "Group One" };
item.Insert();
//Update Data
item.GroupName = "Group Two";
item.Update();
//Insert or Update Data
item.Save();
//Logic Delete
item.Delete();
//Recover Logic Delete
item.Restore();
//Get the object by the primary key
var item = UserGroup.Find(1);
//Query Data
var items = UserGroup.Where(a => a.Id > 10).ToList();
{ENTITY_TYPE}.Select
returns a query object, the same as FreeSql.ISelect
.
In the multi-table query, the logic delete condition will be attached to the query of each table.
For more information about query data, please refer to: https://github.com/2881099/FreeSql/wiki/Query-Data
Transaction Suggestion
Because the AsyncLocal
platform is not compatible, the transaction is managed by the outside.
static AsyncLocal<IUnitOfWork> _asyncUow = new AsyncLocal<IUnitOfWork>();
BaseEntity.Initialization(fsql, () => _asyncUow.Value);
At the beginning of Scoped
: _asyncUow.Value = fsql.CreateUnitOfWork();
(You can also use the UnitOfWorkManager
object to get uow)
At the end of Scoped
: _asyncUow.Value = null;
as follows:
using (var uow = fsql.CreateUnitOfWork())
{
_asyncUow.Value = uow;
try
{
//todo ... BaseEntity internal CURD method keeps using uow transaction
}
finally
{
_asyncUow.Value = null;
}
uow.Commit();
}