以下のような表があります。タイプが固定および普通預金の口座があります。ユーザー1のすべてのアカウントのステータスを更新する必要があります。このユーザーには10000のアカウントがあります。基本的に、ロジックは次のSQLストアドプロシージャスクリプトに示すようになります。スクリプトの実行には1秒未満(83ミリ秒)しかかかりません。
しかし、LINQ to SQLを使用してORMに変換すると、 3分(204814ミリ秒)以上かかります。少なくとも240,000%遅くなります。
このパフォーマンスの低下を克服するのに役立つLINQtoSQL(または他の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を適用した後のコード
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";
}
}
}
参照