1 namespace Example.Infrastructure.Repository 2 { DbSettings 4 { 5 public DbSettings() 6 { ; 8 } NameOrConnectionString { get; set; } RowVersionNname { get; set; } Debug { get; set; } UnitTest { get; set; } IDbConnectionFactory DbConnectionFactory { get; set; } List<object> EntityMaps { get; set; } = new List<object>(); List<object> ComplexMaps { get; set; } = new List<object>(); 22 } 23 }
3.定义SqlServerDbContext和VersionDbContext,解决使用开放式并发连接时,MySql等数据库无法自动生成RowVersion的问题。(1)适用于SqlServer、SqlServeCe的SqlServerDbContext
1 namespace Example.Infrastructure.Repository 2 { SqlServerDbContext : EfDbContext 4 { 5 private DbSettings _dbSettings; SqlServerDbContext(IConfiguration configuration, ILogger logger, DbSettings dbSettings) 8 : base(configuration, logger, dbSettings) 9 { 10 this._dbSettings = dbSettings; 11 } OnModelCreating(DbModelBuilder modelBuilder) 14 { 15 base.OnModelCreating(modelBuilder); 16 modelBuilder.Properties().Where(o => o.Name == this._dbSettings.RowVersionNname).Configure(o => o.IsRowVersion()); 17 base.SetInitializer<SqlServerDbContext>(); 18 } 19 } 20 }
(2)适用于Myql、Sqlite等数据库的VersionDbContext。使用手动更新Version,通过GUID保证版本号唯一。
1 namespace Example.Infrastructure.Repository 2 { VersionDbContext : EfDbContext 4 { 5 private DbSettings _dbSettings; VersionDbContext(IConfiguration configuration, ILogger logger, DbSettings dbSettings) 8 : base(configuration,logger,dbSettings) 9 { 10 this._dbSettings = dbSettings; 11 } OnModelCreating(DbModelBuilder modelBuilder) 14 { 15 base.OnModelCreating(modelBuilder); 16 modelBuilder.Properties().Where(o => o.Name == this._dbSettings.RowVersionNname) 17 .Configure(o => o.IsConcurrencyToken().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)); 18 base.SetInitializer<VersionDbContext>(); 19 } SaveChanges() 22 { 23 this.ChangeTracker.DetectChanges(); 24 var objectContext = ((IObjectContextAdapter)this).ObjectContext; 25 foreach (ObjectStateEntry entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added)) 26 { 27 var v = entry.Entity; 28 if (v != null) 29 { 30 var property = v.GetType().GetProperty(this._dbSettings.RowVersionNname); 31 if (property != null) 32 { 33 var value = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()); 34 property.SetValue(v, value); 35 } 36 } 37 } .SaveChanges(); 39 } 40 } 41 }
4.使用XUnit、Rhino.Mocks和SqlServerCe进行单元测试这是参考nopcommerce中的做法,nopcommerce使用的NUnit需要安装NUnit扩展,XUnit只需要通过Nuget引入程序包,看看GitHub上的aspnet源码,微软也在使用XUnit。