![]() |
VOOZH | about |
dotnet add package Common.EFCore --version 1.7.0
NuGet\Install-Package Common.EFCore -Version 1.7.0
<PackageReference Include="Common.EFCore" Version="1.7.0" />
<PackageVersion Include="Common.EFCore" Version="1.7.0" />Directory.Packages.props
<PackageReference Include="Common.EFCore" />Project file
paket add Common.EFCore --version 1.7.0
#r "nuget: Common.EFCore, 1.7.0"
#:package Common.EFCore@1.7.0
#addin nuget:?package=Common.EFCore&version=1.7.0Install as a Cake Addin
#tool nuget:?package=Common.EFCore&version=1.7.0Install as a Cake Tool
一个功能完善的 Entity Framework Core 扩展库,提供了 Repository 模式、Unit of Work 模式,并针对 PostgreSQL 进行了优化,适合企业级应用开发。
dotnet add package Common.EFCore
dotnet add package Common.EFCore.PostgreSQL
在 Startup.cs 或 Program.cs 中配置服务:
// 配置自增ID生成器
services.AddAutoGenerationId();
// 配置 EF Core 和 DbContext
builder.Services.AddEntityFramework<OpenDbContext>(config =>
{
config.ConnectionString = builder.Configuration["ConnectionStrings:Default"];
config.Schema = "public"; // PostgreSQL Schema
config.WorkId = 1; // 机器ID,用于分布式ID生成
})
.AddUnitOfWork<OpenDbContext>();
/// <summary>
/// 用户信息
/// </summary>
public class User : IdentityBaseEntity
{
private User() { }
public User(string account, string password, bool isValid) : this()
{
Account = account;
Password = password;
IsValid = isValid;
UserName = account;
CreateTime = DateTime.Now.ToUnspecifiedDateTime();
}
/// <summary>
/// 账号
/// </summary>
public string Account { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 是否有效
/// </summary>
public bool IsValid { get; set; }
}
| 基类 | 说明 | 包含字段 |
|---|---|---|
IdentityBaseEntity |
带主键的基础实体 | Id |
IdentityBaseEntity<TKey> |
泛型主键的基础实体 | Id |
IdentityOperatorEntity<TKey> |
包含审计字段的实体 | Id, Creator, CreateTime |
IdentityOperatorStatusEntity<TKey> |
包含审计和状态的实体 | Id, Creator, CreateTime, Updater, UpdateTime, IsDeleted |
public class OpenDbContext : DbContext
{
public OpenDbContext(DbContextOptions<OpenDbContext> options)
: base(options) { }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
base.OnModelCreating(modelBuilder);
}
}
或者继承 BaseDbContext(会自动配置 OnModelCreating):
public class OpenDbContext : BaseDbContext
{
public OpenDbContext(DbContextOptions<OpenDbContext> options)
: base(options) { }
public DbSet<User> Users { get; set; }
}
public class UserConfiguration : EntityTypeConfigurationIdentity<User, long>
{
public override void Configure(EntityTypeBuilder<User> builder)
{
base.Configure(builder);
builder.Property(e => e.Account)
.IsRequired()
.HasMaxLength(50);
builder.Property(e => e.UserName)
.HasMaxLength(100);
builder.HasIndex(e => e.Account).IsUnique();
}
}
EntityTypeConfigurationIdentity<T> - 基础实体配置EntityTypeConfigurationIdentity<T, TKey> - 泛型主键实体配置EntityTypeConfigurationIdentityOperator<T, TKey> - 包含审计字段的实体配置EntityTypeConfigurationIdentityOperatorStatus<T, TKey> - 完整实体配置public class UserService
{
private readonly IBaseRepository<User> _userRep;
public UserService(IBaseRepository<User> userRep)
{
_userRep = userRep;
}
// 添加用户(自动保存)
public async Task AddAsync(User user)
{
await _userRep.AddAsync(user, true);
}
// 获取用户
public async Task<User?> GetByIdAsync(long id)
{
return await _userRep.GetByIdAsync(id);
}
// 查询用户
public async Task<User?> GetByAccountAsync(string account)
{
return await _userRep.GetAsync(x => x.Account == account);
}
// 分页查询
public async Task<(List<User> items, int total)> GetPageListAsync(int pageIndex, int pageSize)
{
int total = 0;
var items = await _userRep.GetPageListAsync(
x => true,
pageIndex,
pageSize,
x => x.CreateTime,
false,
ref total
);
return (items, total);
}
// 更新用户
public async Task UpdateAsync(User user)
{
await _userRep.UpdateAsync(user, true);
}
// 删除用户
public async Task DeleteAsync(long id)
{
await _userRep.DeleteAsync(x => x.Id == id, true);
}
// 批量删除
public async Task DeleteByAccountAsync(string account)
{
await _userRep.DeleteAsync(x => x.Account == account, true);
}
}
public class OrderService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IBaseRepository<Order> _orderRep;
private readonly IBaseRepository<OrderItem> _orderItemRep;
public OrderService(
IUnitOfWork unitOfWork,
IBaseRepository<Order> orderRep,
IBaseRepository<OrderItem> orderItemRep)
{
_unitOfWork = unitOfWork;
_orderRep = orderRep;
_orderItemRep = orderItemRep;
}
// 方式1:使用 CommitTransactionAsync(Lambda表达式方式)
public async Task CreateOrderAsync(Order order, List<OrderItem> items)
{
await _unitOfWork.CommitTransactionAsync(async () =>
{
await _orderRep.AddAsync(order);
foreach (var item in items)
{
item.OrderId = order.Id;
await _orderItemRep.AddAsync(item);
}
});
}
// 方式2:使用 BeginTransactionScopeAsync(显式事务作用域,推荐)
public async Task CreateOrderWithScopeAsync(Order order, List<OrderItem> items)
{
await using var scope = await _unitOfWork.BeginTransactionScopeAsync();
try
{
await _orderRep.AddAsync(order);
foreach (var item in items)
{
item.OrderId = order.Id;
await _orderItemRep.AddAsync(item);
}
await scope.CommitAsync();
}
catch
{
await scope.RollbackAsync();
throw;
}
}
// 方式3:手动管理事务
public async Task CreateOrderAsync2(Order order, List<OrderItem> items)
{
await using var tran = await _unitOfWork.GetDatabase().BeginTransactionAsync();
try
{
await _orderRep.AddAsync(order);
foreach (var item in items)
{
item.OrderId = order.Id;
await _orderItemRep.AddAsync(item);
}
await _unitOfWork.SaveChangesAsync();
await tran.CommitAsync();
}
catch
{
await tran.RollbackAsync();
throw;
}
}
}
当需要使用多个数据库时:
// 配置多个 DbContext
services.AddEntityFramework<MainDbContext>(config =>
{
config.ConnectionString = builder.Configuration["ConnectionStrings:Main"];
config.Schema = "public";
})
.AddUnitOfWork<MainDbContext>();
services.AddEntityFramework<LogDbContext>(config =>
{
config.ConnectionString = builder.Configuration["ConnectionStrings:Log"];
config.Schema = "public";
})
.AddUnitOfWork<LogDbContext>();
// 使用时指定 DbContext 类型
public class MultiDbService
{
private readonly IBaseRepository<User, MainDbContext> _userRep;
private readonly IBaseRepository<OperationLog, LogDbContext> _logRep;
private readonly IUnitOfWork<MainDbContext> _mainUnitOfWork;
private readonly IUnitOfWork<LogDbContext> _logUnitOfWork;
public MultiDbService(
IBaseRepository<User, MainDbContext> userRep,
IBaseRepository<OperationLog, LogDbContext> logRep,
IUnitOfWork<MainDbContext> mainUnitOfWork,
IUnitOfWork<LogDbContext> logUnitOfWork)
{
_userRep = userRep;
_logRep = logRep;
_mainUnitOfWork = mainUnitOfWork;
_logUnitOfWork = logUnitOfWork;
}
}
在批量更新时,根据某些条件决定是否更新特定字段:
// 示例1:当值不为 null 时才更新
string? email = GetUserEmailInput();
string? phone = GetUserPhoneInput();
await repository.UpdateAsync(
x => x.Id == userId,
x => x.SetPropertyIfNotNull(u => u.Email, email)
.SetPropertyIfNotNull(u => u.Phone, phone)
);
// 示例2:当字符串不为空白时才更新
string? userName = GetUserNameInput();
await repository.UpdateAsync(
x => x.Id == userId,
x => x.SetPropertyIfNotNullOrWhiteSpace(u => u.UserName, userName)
.SetProperty(u => u.UpdateTime, DateTime.Now) // 无条件更新
);
// 示例3:根据布尔条件决定是否更新
bool shouldActivate = CheckActivationCondition();
await repository.UpdateAsync(
x => x.Id == userId,
x => x.SetPropertyIfTrue(shouldActivate, u => u.IsActive, true)
.SetPropertyIfTrue(shouldActivate, u => u.ActivationDate, DateTime.Today)
);
// 示例4:使用自定义条件
int newScore = GetScore();
await repository.UpdateAsync(
x => x.Id == userId,
x => x.SetPropertyIf(score => score > 0, u => u.Score, newScore)
);
// 示例5:混合使用普通 SetProperty 和条件更新
await repository.UpdateAsync(
x => x.IsActive == false,
x => x.SetProperty(u => u.UpdateTime, DateTime.Now) // 无条件更新
.SetPropertyIfNotNull(u => u.LastLoginIp, userIp) // 条件更新
.SetPropertyIfNotNullOrWhiteSpace(u => u.Comment, comment) // 条件更新
);
| 方法 | 描述 | 适用版本 |
|---|---|---|
SetPropertyIfTrue(condition, property, value) |
当 condition 为 true 时才设置属性 | .NET 10+ |
SetPropertyIfNotNull(property, value) |
当 value 不为 null 时才设置属性(引用类型) | .NET 10+ |
SetPropertyIfNotNullOrWhiteSpace(property, value) |
当 value 不为 null 或空白时才设置属性(字符串) | .NET 10+ |
SetPropertyIf(condition, property, value) |
使用自定义条件判断是否设置属性 | .NET 10+ |
public class SqlQueryService
{
private readonly IUnitOfWork _unitOfWork;
public SqlQueryService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
// 执行 SQL 命令
public async Task<int> ExecuteSqlAsync(string sql, params object[] parameters)
{
return await _unitOfWork.ExecuteSqlCommand(sql, parameters);
}
// 查询标量值
public async Task<T> ExecuteScalarAsync<T>(string sql, params object[] parameters)
{
return await _unitOfWork.ExecuteScalar<T>(sql, parameters);
}
// SQL 查询列表
public async Task<List<User>> SqlQueryListAsync(string sql, params object[] parameters)
{
return await _unitOfWork.GetDatabase().SqlQueryList<User>(sql, parameters);
}
// SQL 查询 DataTable
public async Task<DataTable> SqlQueryDataTableAsync(string sql, params object[] parameters)
{
return await _unitOfWork.GetDatabase().SqlQueryDataTable(sql, parameters);
}
}
// 使用 GetPageRequest 进行分页
var request = new GetPageRequest
{
PageIndex = 1,
PageSize = 20,
OrderField = "CreateTime",
OrderType = "desc"
};
int total = 0;
var users = await _userRep.GetPageListAsync(request, ref total);
// 或者使用 IQueryable 分页
IQueryable<User> query = _userRep.GetQueryable();
var (items, totalCount) = await query.ToPageListAsync(1, 20);
| 方法 | 说明 |
|---|---|
GetByIdAsync(id) |
根据ID获取实体 |
GetAsync(predicate) |
根据条件获取单个实体 |
GetListAsync(predicate) |
根据条件获取实体列表 |
GetPageListAsync(...) |
分页查询 |
AnyAsync(predicate) |
判断是否存在符合条件的记录 |
CountAsync(predicate) |
统计符合条件的记录数 |
GetQueryable() |
获取 IQueryable 用于自定义查询 |
| 方法 | 说明 |
|---|---|
AddAsync(entity, saveChanges = false) |
添加实体 |
AddAsync(entities, saveChanges = false) |
批量添加 |
UpdateAsync(entity, saveChanges = false) |
更新实体 |
UpdateAsync(predicate, expression, saveChanges = false) |
批量更新 |
DeleteAsync(entity, saveChanges = false) |
删除实体 |
DeleteAsync(predicate, saveChanges = false) |
批量删除 |
| 方法 | 说明 |
|---|---|
SaveChangesAsync() |
保存更改 |
CommitTransactionAsync(action) |
在事务中执行操作(Lambda方式) |
BeginTransactionScopeAsync() |
开启显式事务作用域(推荐) |
GetDatabase() |
获取数据库上下文 |
ExecuteSqlCommand(sql, parameters) |
执行 SQL 命令 |
ExecuteScalar<T>(sql, parameters) |
查询标量值 |
GetRepository<TEntity>() |
获取指定实体的仓储 |
| 方法 | 说明 |
|---|---|
CommitAsync() |
提交事务 |
RollbackAsync() |
回滚事务 |
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ConnectionString |
string | - | 数据库连接字符串 |
Schema |
string | "public" | PostgreSQL Schema 名称 |
WorkId |
int | 0 | 机器ID,用于分布式ID生成 |
IsSnakeCaseNaming |
bool | false | 是否使用蛇形命名 |
该库默认使用无时区 DateTime (timestamp without time zone),以避免 PostgreSQL 时区问题。如需使用有时区的时间,可以在配置中使用
IsTimeZoneDateTime。
builder.Property(x => x.CreateTime)
.IsTimeZoneDateTime(); // 使用有时区的时间
当有多个 DbContext 时,需要指定 DbContext 类型:
IBaseRepository<User, MainDbContext> repository
// 追踪查询(默认)
var user1 = await _userRep.GetByIdAsync(id);
// 非追踪查询(只读场景性能更好)
var user2 = await _userRep.GetQueryable()
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id);
使用 IdentityOperatorStatusEntity 基类,它包含 IsDeleted 字段:
// 软删除
await _userRep.UpdateAsync(
x => x.Id == userId,
x => x.SetProperty(u => u.IsDeleted, true)
);
// 查询时过滤已删除
var users = await _userRep.GetListAsync(x => !x.IsDeleted);
该库提供了三种事务管理方式,各有适用场景:
CommitTransactionAsync)await _unitOfWork.CommitTransactionAsync(async () =>
{
// 业务逻辑
});
适用场景:简单事务,代码量少的操作
BeginTransactionScopeAsync)推荐await using var scope = await _unitOfWork.BeginTransactionScopeAsync();
try
{
// 业务逻辑
await scope.CommitAsync();
}
catch
{
await scope.RollbackAsync();
throw;
}
适用场景:
await using var tran = await _unitOfWork.GetDatabase().BeginTransactionAsync();
try
{
// 业务逻辑
await tran.CommitAsync();
}
catch
{
await tran.RollbackAsync();
throw;
}
适用场景:需要直接访问 EF Core 事务对象
推荐使用显式事务作用域,因为它提供了:
ITransactionScope 接口,提供更清晰的事务管理方式BeginTransactionScope 和 BeginTransactionScopeAsync 方法CommitTransactionAsync 方法继续可用SetPropertyIfTrue - 当条件为 true 时才设置属性SetPropertyIfNotNull - 当值不为 null 时才设置属性SetPropertyIfNotNullOrWhiteSpace - 当字符串值不为 null 或空白时才设置属性SetPropertyIf - 支持自定义条件的属性设置SetProperty 混合使用IsUnTimeZoneDateTime 方法默认值问题GetListAsync 方法响应IBaseRepository 支持指定 DbContextGetDatabase 方法ToPageListAsync 的扩展IUnitOfWork<IEntity> 在多上下文中保存失败的问题IUnitOfWork,默认会添加一个 IUnitOfWorkToPageListAsyncSetDelete 为 SetDeletedPropertyBuilderExtensions 迁移到该程序集BaseRepository 作为公共的操作,且方法为虚方法IBaseRepository 中的同步方法QueryableExtensions 类更新GetPageRequest 增加一个查询关键字EFCoreExtension 内容迁移到工作单元下services.AddUnitOfWork<BaseDbContext>()System.Linq.Dynamic.CoreAddEntityBase 变更为 AddIdHelper()OrderBy 排序方法QueryableExtensions 扩展,分页支持返回总条数,如果参数错误抛出异常QueryableExtensions 扩展AddEntityBaseIBaseRepository 接口编写| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 net6.0 is compatible. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 is compatible. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 5 NuGet packages that depend on Common.EFCore:
| Package | Downloads |
|---|---|
|
Common.EFCore.PostgresSql
操作PostgresSql基础方法 |
|
|
Common.EFCore.InMemory
封装基本的EFCore操作内存数据库的方法 |
|
|
Common.EFCore.MySQL
封住简单操作MySQL的方法 |
|
|
Common.EFCore.SQLite
封装了一些SQLite相关的方法 |
|
|
Common.EFCore.SQLServer
基本的对sqlserver增删改查的封装 |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.7.0 | 218 | 5/17/2026 |
| 1.6.2 | 142 | 2/26/2026 |
| 1.6.1 | 129 | 2/11/2026 |
| 1.6.0 | 214 | 2/9/2026 |
| 1.5.0 | 270 | 11/15/2025 |
| 1.4.3 | 349 | 9/1/2025 |
| 1.4.2 | 568 | 8/26/2025 |
| 1.4.1 | 307 | 8/17/2025 |
| 1.4.0 | 403 | 8/13/2025 |
| 1.4.0-beta8 | 285 | 8/12/2025 |
| 1.4.0-beta7 | 207 | 8/9/2025 |
| 1.4.0-beta6 | 197 | 8/9/2025 |
| 1.4.0-beta5 | 205 | 7/29/2025 |
| 1.4.0-beta4 | 687 | 7/23/2025 |
| 1.4.0-beta3 | 319 | 5/6/2025 |
| 1.4.0-beta1 | 452 | 3/1/2025 |
| 1.3.2 | 314 | 8/12/2024 |
| 1.3.1 | 522 | 8/11/2024 |
| 1.3.0 | 254 | 7/27/2024 |
| 1.3.0-beta4 | 183 | 7/27/2024 |