> GetByIdAsync(int id); TaskT>> GetAllAsync(); Task AddAsync(T entity);...= context; _dbSet = context.SetT>(); } publicasync TaskT?...> GetByIdAsync(int id) => await _dbSet.FindAsync(id); publicasync TaskT>> GetAllAsync...() => await _dbSet.ToListAsync(); public async Task AddAsync(T entity) => await _dbSet.AddAsync...可测试性:更简单的单元测试 直接注入DbContext会因EF Core与内存数据库的兼容性问题导致单元测试困难。
单例的MongoClient 基于MongoDB的最佳时间,对于MongoClient最好设置为单例注入,因为在MongoDB.Driver中MongoClient已经被设计为线程安全可以被多线程共享,...GetCollectionT>(string name) { return _database.GetCollectionT>(name); } public...(async (session) => await _dbSet.DeleteOneAsync(Builders.Filter.Eq(_keyField, new ObjectId(id...(session) => await _dbSet.ReplaceOneAsync(item => item.Id == entity.Id, entity)); } public...return ReadPreference.SecondaryPreferred; } #endregion } 工作单元:UnitOfWork 在实际项目中,在对多个
主键 默认情况下,EF CORE会将实体中命名为Id或者[TypeName]Id的属性映射为数据库表中的主键。当然有些开发者不喜欢将主键命名为Id,EF CORE也提供了两种方式进行主键的相关设置。...生成值 前文中已经介绍过,假如属性被命名为Id/[TypeName]Id的形式,EF CORE会将该属性设置为主键。...默认值 默认值与计算列定义十分相似,只是计算列无法由用户手动输入。而默认值更多指的是当用户不手动输入时,使用默认值进行数据库相应列的填充。...备用键 备用键在之前的小节中已经提过,使用以下代码配置的列将自动设置为唯一标识列。...,HasValue提供新增或修改实体时,根据实体类型将不同的标识自动写入标识列中。
在 .NET 开发中,很容易陷入编码实践,这些实践可能会悄无声息地降低应用程序的质量、安全性和可维护性。这些“无声代码剧透”可能会引入错误,导致安全漏洞,并使代码难以阅读和更新。...UpdateOrderStatus No Using Statements:数据库连接是手动打开和关闭的,没有块,如果出现异常,连接可能会被取消关闭。...= context.SetT>(); } publicvirtualasyncTaskT>GetByIdAsync(int id)=>await _dbSet.FindAsync(id...); publicvirtualasyncTaskAddAsync(T entity)=>await _dbSet.AddAsync(entity); publicvirtualasyncTaskUpdateAsync...控制器中 MediatR 命令的示例用法 设置 MediatR 后,控制器可以轻松发送命令并处理响应。
乐观并发控制:并发令牌 Update T_Houses set Owner=新值 where Id=1 and Owner=旧值 当Update的时候,如果数据库中的Owner值已经被其他操作者更新为其他值了...,然后使用IsRowVersion()把这个属性设置为RowVersion类型,这样这个属性对应的数据库列就会被设置为ROWVERSION类型。...对于ROWVERSION类型的列,在每次插入或更新行时,数据库会自动为这一行的ROWVERSION类型的列其生成新值。...总结:如果有一个确定的字段要被进行并发控制,那么使用IsConcurrencyToken()把这个字段设置为并发令牌即可;如果无法确定一个唯一的并发令牌列,那么就可以引入一个额外的属性设置为并发令牌,并且在每次更新数据的时候...,手动更新这一列的值。
IUnitOfWork UnitOfWork { get; } TEntity Add(TEntity entity); Task AddAsync.../// 继承了上面的接口 IRepository,也就是说拥有了上面定义的所有方法 /// 另外一个,它实现了几个跟 Id 相关的操作的方法 /// </summary...DbContext.Add(entity).Entity; } public virtual Task AddAsync(TEntity entity...Address 这个值类型作为同一个表的字段来设置 builder.OwnsOne(o => o.Address, a => {...,这个映射关系可以组织为一个目录,为每一个领域模型设置一个类型来定义,并且这个过程是强类型的,这样的结构,便于后期维护 另外仓储层的话,定义了一个 IOrderRepository,仅仅实现了 IRepository
(3)返回类型:只能返回 3 种类型(void、Task 和 TaskT>)。Task 和 TaskT> 标识返回的对象会在将来完成工作,表示调用方法和异步方法可以继续执行。...async/await 结构 现在先来简单分析一下这三种返回值类型:void、Task 和 TaskT> (1)TaskT>:调用方法要从调用中获取一个 T 类型的值,异步方法的返回类型就必须是...调用方法从 Task 的 Result 属性获取的就是 T 类型的值。...如果异步方法的返回类型为 Task 或 TaskT>,会创建一个 Task 对象,标识需要异步完成的任务,然后将 Task 返回来调用方法。...b.Task:设置 Task 的属性并退出。 c.TaskT>:设置 Task 的属性和返回值(Result 属性)并退出。 ④同时,调用方法将继续执行,从异步方法获取 Task 对象。
导航属性 由一个属性可以访问到另外一种类型的实体叫做导航属性 单向导航:不设置反向的属性,然后配置的时候WithMany()不设置参数即可。...EF Core中的异步方法 SaveChanges()、SaveChangesAsync()、AddAsync()、AddRangeAsync()、AllAsync()、AnyAsync、AverageAsync...foreach(Book b in books.Skip(3).Take(6)) { } 局限性: SQL 查询必须返回实体类型对应数据库表的所有列; 结果集中的列名必须与属性映射到的列名称匹配。...执行SaveChanges()等方法时,EF Core将会把存储的快照中的值与实体的当前值进行比较。...未改变(Unchanged):DbContext正在跟踪此实体,该实体存在于数据库中,其属性值和从数据库中读取到的值一致,未发生改变。
,该集合属性里面的元素是另一个实体时,则默认未一对多关系,即使没有显示的指定一对多的关系,EF会默认的设置主外键(主从)关系 (3)、一对一的实体关系,需要手动设置主从关系 (4)、多对多无载荷关系实体...{ //暴露City的DbSet类型的属性 public DbSet Citys { get; set; } //暴露Town的DbSet...,EF会默认将长得最像Id的属性(且类型为GUID)设为主键,如果类中的属性(Property)名称为 ID (不区分大小写)或 ClassNameID(类名 + ID),Code First 则推断这个属性为主键...如果主键属性的类型为数字型或 GUID 则会被当成标识列(Identity Column) 4、关系(外键/导航属性)约定Relationship(Foreign Key/Navigation Properties.... (2)、当关联实体的外键属性被设置为不为空,Code First会设置级联删除,反之不会。
首先数据库中主外键的定义: 主键 外键 定义: 唯一标识一条记录,不能有重复的,不允许为空 表的外键是另一表的主键, 外键可以有重复的, 可以是空值 作用: 用来保证数据完整性 用来和其他表建立联系用的...而称ArtistID属性为外键属性(foreign key),因为与模型对应的数据库中,专辑表(Album)和艺术家(Artist)表存在对应的外键关系,即ArtistID是Album表的外键!...该派生类具有一个或多个DbSetT>类型的属性,类型DbSetT>中的每一个T代表一个想要持久保存的对象。...如果不配置从模型到数据库中表和列的具体映射,EF将使用约定创建一个数据库模式。 显式的为代码优先数据上下文配置连接很简单,即向web.config文件中添加一个连接字符串。 ?...如果不希望在每个Action的参数中都应用Bind属性,可以在Model定义中指定: ? 当绑定引发异常时,使用UpdateModel()方法会直接抛出异常。
支持SpecificationT>模式,使你能够动态构建查询,即延迟查询构建。 具有针对你的查询的数据库级投影支持。 支持针对你的关系型数据库运行原始SQL命令。...新建UserInfo类 [Table("UserInfo")] public class UserInfo { [Key] public int Id...TestDbContext(DbContextOptions options) : base(options) { } public DbSet...UserInfo { Name = "daydayup", Age = 28, Email = "daydayup@example.com" }; await _repository.AddAsync...internal class Program { static async Task Main(string[] args) { //设置依赖注入容器
我们定义完模型,还需要让EF上下文你知道应该映射那些模型,此时我们需要通过 DbSet 属性来暴露模型的。...**id***,推断属性为主键(如果类中没有id属性,会查找定义成***类名称+id***的属性,将这个属性作为主键)。...如果主键类型是***int*** 或者 guid 类型,主键将会被映射为自增长标识列。...如果一个类中既没有id属性,也没有类名+id的属性,那么代码在运行时将会报错,因为EF没有找到符合要求的字段创建主键。...简单的说就是:一个复杂类型作为已存在对象的属性,EF会将复杂类型的类映射到已存在的表中,已存在的表包将包含这些列,而不是将复杂类型映射成另外单独的一张表。
当然了,如果有小伙伴有更好的方法也可以分享出来呀。 1.2 配置文件的加载或者实体对象的托管 如果我们不使用配置文件的话,就必须在EF Core的上下文类里添加一个类型是DbSetT>的属性。...null 外键属性设置为 null Restrict None None 而对于不可为NULL的外键来说,枚举DeleteBehavior的值起以下作用: 行为名称 对内存中的依赖项/子项的影响 对数据库中的依赖项.../子项的影响 Cascade(默认) 删除实体 删除实体 ClientSetNull SaveChanges 引发异常 None SetNull 引发 SaveChanges SaveChanges 引发异常...在查询表达式写法中,排序应该这样的写的: var results = from t in context.Set() orderby t.Id...).Where(t=>true).OrderBy(t=>t.Id); 分页只能通过方法链的形式进行分页,这里提供一个分页的工具方法: public static IQueryableT> Paging
Framework CodeFirst尝试 的基础上给Order添加一个"Employee”属性,然后运行,不出意外的话你将看到如下异常: ? ...=> t.ID) .ForeignKey("dbo.Orders", t => t.OrderID, cascadeDelete: true)...AutomaticMigrationsEnabled:获取或设置 指示迁移数据库时是否可使用自动迁移的值。 2. ...AutomaticMigrationDataLossAllowed:获取或设置 指示是否可接受自动迁移期间的数据丢失的值。...如果设置为false,则将在数据丢失可能作为自动迁移一部分出现时引发异常。
=> t.ExcludeFromMigrations()); } 属性和列配置 包含和排除的属性 列名 键 自动生成列 包含和排除的属性 实体属性:https://docs.microsoft.com/...tabs=data-annotations 按照约定,将名为 Id 或的属性 Id 配置为实体的主键。...生成的值:https://docs.microsoft.com/zh-cn/ef/core/modeling/generated-properties?...().ToString(); 新增一条数据,返回 Id 是自动生成的 028.jpg 通过数据批注方式添加创建时间,修改时间默认值 Entity /// /// 创建时间 ///...此属性也被视为并发标记,这确保了在你查询行后,如果正在更新的行发生了更改,则会出现异常。
异步操作时需要注意的要点 1.使用异步方法返回值应当避免使用void 在使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点 无法得知异步函数的状态机在什么时候执行完毕...使用ValueTaskT>代替 static async Task Main(string[] args) { await AddAsync(1, 1); } static ValueTask...但是也导致了上下文问题,RunAsync不在以UI线程调用 // Result和Wait()方法如果出现异常,异常将被包装为AggregateException进行抛出, return...代码更容易修改(例如:增加一个using) 异步的方法诊断起来更加容易(例如:调试,挂起) 抛出的异常将自动包装在返回的任务之中,而不是抛出实际异常 下面这个错误的例子是将Task直接返回给了调用者...,从而生成异步的结果值,但是这样很容易导致线程池饥饿 下面这个例子就有可能导致线程池饥饿,因为当如果没有缓存人员数据时,将阻塞请求线程 public class PersonController : Controller
T>,T 就是实体的类型 每一个属性都是读写属性 read/write ( get/set ) 在这里,DbContext 基类通过反射来获取映射到数据库的实体。...方法,然后将Order类映射到efdemo架构Order表中,再然后为OrderID设置规则,规定它为标识列,自增,不能为空,且映射到表中的TheOrderID列上面。...作为自动增长的标识列。...在 EF 中,这被称为并发标识 concurrenty token,在这篇文章中,我使用 SQL Server 的 time-stamp 特性,这需要在表中增加一个 time-stamp 类型的列,我们通过它来实现乐观并发...由 SQL Server 在每次记录被更新的时候维护这个列。为了告诉 EF 在实体中有一个属性表示并发标识,你可以通过标签 [ConcurrencyCheck] 来标识这个属性,或者使用模型构建器。
DbEntityValidationException ex) { var e = ex.EntityValidationErrors; } catch (Exception ex) { } 一层一层地打开,看到真正导致异常的原因...那么必定是未进行任何设置的实体属性默认是IsOptional()。这跟表结构中的字段类型设置为Not Null有无关联呢,从测试结果看就本类应用无必然联系。...执行操作 涉及到两次修改操作,两次操作构造了两个实例,但是实例的属性Id有相同的值。...t.Email).IsModified = true; int num = db.SaveChanges(); } 3 未给主键赋值或赋给主键一个不存在的值...赋给主键一个不存在的值,令Id=4(在数据库表中不存在Id为4的一条记录)抛出的异常与上面的相同。
异步操作时需要注意的要点 1.使用异步方法返回值应当避免使用void 在使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点 无法得知异步函数的状态机在什么时候执行完毕...,可能就会导致死锁' 线程池饥饿 *数据结构损坏(如果代码异常运行) 所以在创建TaskCompletionSoureceT>时,应该使用TaskCreationOption.RunContinuationAsyncchronously...代码更容易修改(例如:增加一个using) 异步的方法诊断起来更加容易(例如:调试,挂起) 抛出的异常将自动包装在返回的任务之中,而不是抛出实际异常 ❌下面这个错误的例子是将Task直接返回给了调用者...使用定时器回调函数 ❌下面例子使用一个返回值为void的异步,将其传递给Timer进行,因此,如果其中任务抛出异常,则整个进程将退出 public class Pinger { private...,从而生成异步的结果值,但是这样很容易导致线程池饥饿 ❌下面这个例子就有可能导致线程池饥饿,因为当如果没有缓存人员数据时,将阻塞请求线程 public class PersonController :
,也会根据购买产品的PV,累加当前经销商的PV值。...10.生成数据库表: 根据前面文章的说明,我们可以依据上述POCO模型生成对应的数据库表,要注意的是,OrderItems可以自动识别为Orders的关联表,其他几个值对象我们要考虑是否是生成 单独的表还是作为相关实体或聚合根的表的列存在...,一般情况下,我们是将这些值对象作为相关聚合根或实体表的列存在的。...public DbSet Order { get; set; } public DbSet OrderItem { get; set...modelBuilder.Entity().OwnsOne(p => p.ProductSKUs); } 从上面代码可以看出,在OnModelCreating时,可以指定6个值对象包含在对应的聚合根和实体相关的表中