我正在寻找插入Entity Framework的最快方法.
我问这个是因为你有一个活跃的TransactionScope并且插入很大(4000+).它可能持续超过10分钟(事务的默认超时),这将导致事务不完整.
我遵循了"不要过早优化"的口头禅并使用Entity Framework编写了我的WCF服务.
但是,我描述了性能和实体框架太慢了.(我的应用程序在大约1.2秒内处理2条消息,其中我正在重写的(传统)应用程序同时执行5-6条消息.(旧应用程序调用sprocs进行数据库访问.)
我的分析指向实体框架占用每条消息的大部分时间.
那么,我的选择是什么?
那里有更好的ORM吗?
(只支持正常读取和写入对象的东西,并且它很快...)
有没有办法让实体框架更快?
(注意:当我说速度更快时,我的意思是从长远来看,而不是第一次调用.(第一次调用很慢(消息为15秒),但这不是问题.我只需要它快速休息的消息.)
一些神秘的第三选项,将帮助我提高我的服务速度.
注意:我的大多数数据库交互都是创建和更新.我做的很少选择和删除.
在数据库优先的场景中使用DbContext时,我发现与ObjectContext相比,添加和删除实体的速度非常慢.如果添加2000个实体并在最后保存更改,DbContext比ObjectContext慢3到5倍(顺便说一句:我知道使用SqlBulkCopy添加大量实体会更好,但这不是重点).如果在每次添加后保存更改,DbContext仍然慢近两倍.当涉及删除时,它甚至变得更糟:当在所有实体删除结束时保存时,DbContext比ObjectContext慢大约18倍.
我使用了我用来比较数据库访问技术和小型控制台应用程序的高度开发的测试应用程序来进行双重检查.两者都显示使用DbContext添加和删除实体的结果不佳.以下是控制台应用程序的结果:
Inserting 2000 entities via DbContext saving changes at the end: 2164ms
Inserting 2000 entities via ObjectContext saving changes at the end: 457ms
Inserting 2000 entities via DbContext saving changes after each object addition: 8420ms
Inserting 2000 entities via ObjectContext saving changes after each object adding: 4857ms
Inserting 2000 entities via DbContext using a new DbContext for each object addition: 4018ms
Deleting 2000 entities via DbContext saving changes at the end: 4794ms
Deleting 2000 entities via ObjectContext saving changes …
Run Code Online (Sandbox Code Playgroud) 我们的代码中有一个通用的更新方法
foreach (var entity in entityList)
{
Context.GetIDbSet<T>().Attach(entity);
Context.SetState(entity, EntityState.Modified);
}
Run Code Online (Sandbox Code Playgroud)
我通过传入一个实体的枚举并按每个实体调用一次来测试它.
我发现的是1000个实体的枚举大约需要47秒才能运行.这是预期的行为吗?或者代码片段有问题吗?
分析显示Attach()方法比SetState()方法慢.
我运行它的测试是在一个有50个属性的实体上,如果有任何影响则没有关系.
我的应用程序运行时需要插入两个表.
让我们说我有表格如下
我的问题是数据量.
我需要向tbl_FirstTable插入超过10,000行,并向tbl_SecondTable插入超过500,000行.
如此冷酷,我使用实体框架如下.
public bool Save_tbl_FirstTable_Vs_tbl_SecondTable(List<tbl_FirstTable> List_tbl_FirstTable, List<tbl_SecondTable> List_tbl_SecondTable)
{
bool IsSuccessSave = false;
try
{
using (DummyDBClass_ObjectContext _DummyDBClass_ObjectContext = new DummyDBClass_ObjectContext())
{
foreach (tbl_FirstTable _tbl_FirstTable in List_tbl_FirstTable)
{
_DummyDBClass_ObjectContext.tbl_FirstTable.InsertOnSubmit(_tbl_FirstTable);
}
foreach (tbl_SecondTable _tbl_SecondTable in List_tbl_SecondTable)
{
_DummyDBClass_ObjectContext.tbl_SecondTable.InsertOnSubmit(_tbl_SecondTable);
}
_DummyDBClass_ObjectContext.SubmitChanges();
IsSuccessSave = true;
}
}
catch (Exception ex)
{
Log4NetWrapper.WriteError(string.Format("{0} : {1} : Exception={2}",
this.GetType().FullName,
(new StackTrace(new StackFrame(0))).GetFrame(0).GetMethod().Name.ToString(),
ex.Message.ToString()));
if (ex.InnerException != null)
{
Log4NetWrapper.WriteError(string.Format("{0} : {1} : InnerException Exception={2}",
this.GetType().FullName,
(new StackTrace(new StackFrame(0))).GetFrame(0).GetMethod().Name.ToString(),
ex.InnerException.Message.ToString()));
}
} …
Run Code Online (Sandbox Code Playgroud) public class UserBuilding
{
[Key, Column(Order = 0)]
public int UserId { get; set; }
[Key, Column(Order = 1)]
public int BuildingId { get; set; }
public int BuildingLevel { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我想要返回属于用户的所有不同建筑物,我会执行以下操作:
database.UserBuildings.Where(b => b.UserId == userId);
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我想从特定用户返回特定建筑物,该怎么办?这样做最"有效"的方式是什么?有没有比以下更好的方法(例如内置函数):
database.UserBuildings.Where(b => b.UserId == userId && b.BuildingId == buildingId);
Run Code Online (Sandbox Code Playgroud) 我看了几篇文章(第一条,第二条关于实体框架,它调用DetectChanges很多次,处理大量数据的工作时,这使得它很慢).
例如,autoDetectChanges
我可以在初始化上下文时禁用,并在调用DetectChanges()
之前调用.SaveChanges()
吗?
上下文是否会识别插入/更改/删除的实体?
var _dbContext = new ProjectContext();
_dbContext.Configuration.AutoDetectChangesEnabled = false;
// add/edit/delete entities
_dbContext.ChangeTracker.DetectChanges();
_dbContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
这种方法应该有效吗?或者它可能会产生隐藏的错误?
我有一个Save
对象,它有多个关联的集合。对象的总大小如下:
对象之间的关系可以从该映射中推断出来,并且在数据库中似乎得到了正确的表示。查询也很好。
modelBuilder.Entity<Save>().HasKey(c => c.SaveId).HasAnnotation("DatabaseGenerated",DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Save>().HasMany(c => c.Families).WithOne(x => x.Save).HasForeignKey(x => x.SaveId);
modelBuilder.Entity<Save>().HasMany(c => c.Countries).WithOne(x => x.Save).HasForeignKey(x => x.SaveId);
modelBuilder.Entity<Save>().HasMany(c => c.Provinces).WithOne(x => x.Save).HasForeignKey(x => x.SaveId);
modelBuilder.Entity<Save>().HasMany(c => c.Pops).WithOne(x => x.Save).HasForeignKey(x => x.SaveId);
modelBuilder.Entity<Country>().HasOne(c => c.Save);
modelBuilder.Entity<Country>().HasMany(c => c.Technologies).WithOne(x => x.Country).HasForeignKey(x => new {x.SaveId, x.CountryId});
modelBuilder.Entity<Country>().HasMany(c => c.Players).WithOne(x => x.Country).HasForeignKey(x => new {x.SaveId, x.CountryId});
modelBuilder.Entity<Country>().HasMany(c => c.Families).WithOne(x => x.Country).HasForeignKey(x => new {x.SaveId, x.OwnerId});
modelBuilder.Entity<Country>().HasMany(c => c.Provinces).WithOne(x => x.Owner);
modelBuilder.Entity<Country>().HasKey(c => new { c.SaveId, c.CountryId });
modelBuilder.Entity<Family>().HasKey(c => new …
Run Code Online (Sandbox Code Playgroud) c# entity-framework mariadb entity-framework-core ef-core-3.1
c# ×4
.net ×1
ado.net ×1
dbcontext ×1
ef-core-3.1 ×1
mariadb ×1
orm ×1
performance ×1
return ×1
row ×1
sql ×1
sql-server ×1