我想按实体框架在表中插入20000条记录,大约需要2分钟.除了使用SP来改善其性能之外,还有什么方法.这是我的代码:
foreach (Employees item in sequence)
{
t = new Employees ();
t.Text = item.Text;
dataContext.Employees.AddObject(t);
}
dataContext.SaveChanges();
Run Code Online (Sandbox Code Playgroud) 我遵循了"不要过早优化"的口头禅并使用Entity Framework编写了我的WCF服务.
但是,我描述了性能和实体框架太慢了.(我的应用程序在大约1.2秒内处理2条消息,其中我正在重写的(传统)应用程序同时执行5-6条消息.(旧应用程序调用sprocs进行数据库访问.)
我的分析指向实体框架占用每条消息的大部分时间.
那么,我的选择是什么?
那里有更好的ORM吗?
(只支持正常读取和写入对象的东西,并且它很快...)
有没有办法让实体框架更快?
(注意:当我说速度更快时,我的意思是从长远来看,而不是第一次调用.(第一次调用很慢(消息为15秒),但这不是问题.我只需要它快速休息的消息.)
一些神秘的第三选项,将帮助我提高我的服务速度.
注意:我的大多数数据库交互都是创建和更新.我做的很少选择和删除.
基本上,我在一个事务中插入35000个对象:
using(var uow = new MyContext()){
for(int i = 1; i < 35000; i++) {
var o = new MyObject()...;
uow.MySet.Add(o);
}
uow.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
这需要永远!如果我使用底层ObjectContext(通过使用IObjectAdapter),它仍然很慢但需要大约20秒.它似乎DbSet<>正在进行一些线性搜索,这需要花费大量时间......
其他人看到这个问题?
我正在运行一个导入,每次运行将有1000个记录.只是在我的假设上寻找一些确认:
以下哪一项最有意义:
SaveChanges()每个AddToClassName()电话.SaveChanges()每n次AddToClassName()呼叫运行一次.SaveChanges()后,所有的的AddToClassName()电话.第一种选择可能是慢的吗?因为它需要分析内存中的EF对象,生成SQL等.
我假设第二个选项是两个世界中最好的,因为我们可以围绕该SaveChanges()调用包装try catch ,并且如果其中一个失败,则一次只丢失n个记录.也许将每个批次存储在List <>中.如果SaveChanges()调用成功,请删除列表.如果失败,请记录项目.
最后一个选项可能最终也会非常慢,因为每个EF对象都必须在内存中才能SaveChanges()被调用.如果保存失败,则不会发生任何事情,对吧?
我有一个在TransactionScope中运行的代码块,在这段代码中,我多次调用DB.选择,更新,创建和删除整个色域.当我执行删除操作时,我使用SqlCommand的扩展方法执行它,如果查询死锁,它将自动重新提交查询,因为此查询可能会遇到死锁.
我相信当遇到死锁并且函数尝试重新提交查询时会发生此问题.这是我收到的错误:
与当前连接关联的事务已完成但尚未处理.必须先处理事务,然后才能使用连接执行SQL语句.
这是执行查询的简单代码(下面的所有代码都在使用TransactionScope执行):
using (sqlCommand.Connection = new SqlConnection(ConnectionStrings.App))
{
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQueryWithDeadlockHandling();
}
Run Code Online (Sandbox Code Playgroud)
以下是重新提交死锁查询的扩展方法:
public static class SqlCommandExtender
{
private const int DEADLOCK_ERROR = 1205;
private const int MAXIMUM_DEADLOCK_RETRIES = 5;
private const int SLEEP_INCREMENT = 100;
public static void ExecuteNonQueryWithDeadlockHandling(this SqlCommand sqlCommand)
{
int count = 0;
SqlException deadlockException = null;
do
{
if (count > 0) Thread.Sleep(count * SLEEP_INCREMENT);
deadlockException = ExecuteNonQuery(sqlCommand);
count++;
}
while (deadlockException != null && count < MAXIMUM_DEADLOCK_RETRIES);
if (deadlockException != null) throw deadlockException; …Run Code Online (Sandbox Code Playgroud) 我正在运行一些运行在一大堆实体上的校正码,因为它的速度会降低,这是因为上下文中跟踪实体的数量会随着每次迭代而增加,这可能需要很长时间,所以我最后会保存更改每次迭代.每次迭代都是独立的,不会改变先前加载的实体.
我知道我可以关闭更改跟踪,但我不想,因为它不是批量插入代码,而是加载实体并计算一些东西,如果数字不正确,请设置新数字并更新/删除/创建一些额外的实体.我知道我可以为每次迭代创建一个新的DbContext,并且可能比在同一个实例中执行所有操作更快,但我认为可能有更好的方法.
所以问题是; 有没有办法清除先前在db上下文中加载的实体?
在数据库优先的场景中使用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) 正如我们许多人所做的那样,我设置了一个简单的循环来从数据库添加多个记录.一个典型的例子是这样的:
// A list of product prices
List<int> prices = new List<int> { 1, 2, 3 };
NorthwindEntities NWEntities = new NorthwindEntities();
foreach (int price in prices)
{
Product newProduct = new Product();
newProduct.Price = price;
NWEntities.Products.AddObject(newProduct);
}
NWEntities.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
然而,当我第一次设置循环时,我直观地写道:
Product newProduct = new Product();
foreach (int price in prices)
{
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
Run Code Online (Sandbox Code Playgroud)
在做了一点阅读之后,几个人提到如果使用方法II,则只会在表格中添加一条记录.这似乎反直觉.这是加载新插入的Add()函数,我认为,在每次调用传入数据后创建一个对象.在循环外声明我的Product对象似乎更好地利用资源,因为这是消耗的唯一开销.每次调用都是对象实例属性的重新赋值,而不是对象实例本身的重构.
有人可以澄清一下吗?我找不到另一个直接处理这个问题的帖子.如果有人在那里请指出.
如何从简单对象的List <>中使用SqlBulkCopy进行大插入?
我是否实现了自定义IDataReader?
我有一个实体列表,我想将它们插入到数据库中.如果实体已经存在于数据库中,则需要跳过该实体.如果它在数据库中但具有不同的值,那么它需要更新.
除了每个项目进行数据库调用之外,还有什么方法可以做到这一点吗?
我的计划是尝试插入,如果抛出键上的唯一约束异常,则执行更新.
c# ×5
ado.net ×3
performance ×2
sql-server ×2
.net ×1
bulkinsert ×1
dbcontext ×1
deadlock ×1
entity ×1
import ×1
loops ×1
orm ×1
savechanges ×1
sql ×1