我有一个如下所示的表格。它有固定和储蓄类型的账户。我需要更新用户 1 的所有帐户的状态。该用户有 10000 个帐户。本质上,逻辑将如以下 SQL 存储过程脚本所示。该脚本只需不到 1 秒即可执行(83 毫秒)。
但是当我使用LINQ to SQL将其转换为 ORM 时,需要 3 分钟以上(204814 毫秒)。它至少慢了240,000% 。
LINQ to SQL(或其他 ORM)中是否存在有助于克服这种性能损失的模式?
什么可以迫使它一次性对数据库进行更新?
注意:我知道从 LINQ 调用存储过程。我不认为这是 ORM 而不是我的选择。
手动存储过程脚本
DECLARE @UserID INT
DECLARE @StatusForFixed VARCHAR(50)
DECLARE @StatusForSavings VARCHAR(50)
SET @UserID = 1
SET @StatusForFixed = 'FrozenFA11'
SET @StatusForSavings = 'FrozenSB22'
UPDATE BankAccount
SET Status =
CASE
WHEN BankAccount.AccountType='Fixed' THEN @StatusForFixed
WHEN BankAccount.AccountType='Savings' THEN @StatusForSavings
END
WHERE AccountOwnerID=@UserID
LINQ 生成的代码示例
Note: This type of statements happen 10000 times
UPDATE [dbo].[BankAccount]
SET [Status] = @p3
WHERE [BankAccountID] = @p0
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [3585]
-- @p3: Input NChar (Size = 10; Prec = 0; Scale = 0) [FrozenSB]
应用ORM后的CODE
public class BankAccountAppService
{
public RepositoryLayer.ILijosBankRepository AccountRepository { get; set; }
public void FreezeAllAccountsForUser(int userId)
{
IEnumerable<DBML_Project.BankAccount> accounts = AccountRepository.GetAllAccountsForUser(userId);
foreach (DBML_Project.BankAccount acc in accounts)
{
acc.Freeze();
}
AccountRepository.UpdateAccount();
}
}
public class LijosSimpleBankRepository : ILijosBankRepository
{
public System.Data.Linq.DataContext Context
{
get;
set;
}
public List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID)
{
IQueryable<DBML_Project.BankAccount> queryResultEntities = Context.GetTable<DBML_Project.BankAccount>().Where(p => p.AccountOwnerID == userID);
return queryResultEntities.ToList();
}
public List<T> GetAllAccountsofType<T>() where T : DBML_Project.BankAccount
{
var query = from p in Context.GetTable<DBML_Project.BankAccount>().OfType<T>()
select p;
List<T> typeList = query.ToList();
return typeList;
}
public virtual void UpdateAccount()
{
Context.SubmitChanges();
}
}
namespace DBML_Project
{
public partial class BankAccount
{
//Define the domain behaviors
public virtual void Freeze()
{
//Do nothing
}
}
public class FixedBankAccount : BankAccount
{
public override void Freeze()
{
this.Status = "FrozenFA";
}
}
public class SavingsBankAccount : BankAccount
{
public override void Freeze()
{
this.Status = "FrozenSB";
}
}
}
参考