使用实体框架和存储过程进行并发检查
Posted
技术标签:
【中文标题】使用实体框架和存储过程进行并发检查【英文标题】:Concurrency checks with Entity Framework and Stored Procedures 【发布时间】:2018-02-27 23:10:34 【问题描述】:我正在使用实体框架并通过存储过程(每个客户端请求)操作 sqlserver 数据库中的数据。 通过存储过程从数据库中提取数据,这些存储过程的结果将填充到 Winforms 应用程序中的 SQLite 数据库。
SQLite 用于额外查询和更改数据,然后在用户同步时通过更新存储过程推送回 sql server db
所有存储过程都在 sql server 上(在应用程序中没有文本/行 sql)
我面临多个用户可能尝试更新同一字段的情况,这给我带来了 2 个问题。
如果它们同时调用相同的存储过程(选择或更新)。 我不确定从编程级别来看我的选择是什么,我无权更改服务器。
如果他们尝试更新的字段已经更新。
对于问题 2,我正在尝试通过对修改进行日期标记来构建检查。 IE。当用户同步 sql server 将该同步日期添加到日期修改列时,如果另一个用户尝试修改同一字段,我想检查他的 sqlite db 上修改的日期并将其与 sql server 中修改的日期进行比较,如果 sql server 的修改日期较新,保留 sql server 值,如果同步用户的修改日期较新,请使用他的...
我研究了在客户端获胜的情况下解决乐观并发问题。
using (var context = new BloggingContext())
var blog = context.Blogs.Find(1);
blog.Name = "The New ADO.NET Blog";
bool saveFailed;
do
saveFailed = false;
try
context.SaveChanges();
catch (DbUpdateConcurrencyException ex)
saveFailed = true;
// Update original values from the database
var entry = ex.Entries.Single();
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
while (saveFailed);
但这似乎只在您使用实体框架直接查询数据库时有效,而不是在您想通过存储过程更新时有效。
我可以使用什么来执行这些类型的检查?
【问题讨论】:
【参考方案1】:好的,这可能不是最好的解决方案,但这是我能够想出的,虽然最初没有经过广泛测试,但似乎还可以。
我不会将此标记为答案,但这是我根据上述问题所做的工作。
同时调用存储过程,为事务创建一个类
public class TransactionUtils
public static TransactionScope CreateTransactionScope()
var transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
transactionOptions.Timeout = TransactionManager.DefaultTimeout;
return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
然后在代码中使用如下:
var newTransactionScope = TransactionUtils.CreateTransactionScope();
try
using (newTransactionScope)
using (var dbContextTransaction = db_context.Database.BeginTransaction(/*System.Data.IsolationLevel.ReadCommitted*/))
try
db_context.Database.CommandTimeout = 3600;
db_context.Database.SqlQuery<UpdateData>("UpdateProc @Param1, @Param2, @Param3, @Param4, @Param5, @Param6, @DateModified",
new SqlParameter("Param1", test1),
new SqlParameter("Param2", test2),
new SqlParameter("Param3", test3),
new SqlParameter("Param4", test4),
new SqlParameter("Param6", test5),
new SqlParameter("DateModified", DateTime.Now)).ToList();
dbContextTransaction.Commit();
catch (TransactionAbortedException ex)
dbContextTransaction.Rollback();
throw;
关于问题 2(并发) 我找不到在 SQL Server 上的数据和我想从 SQLite 更新的数据(2 个不同的上下文)之间使用内置并发检查的方法
所以我将修改日期存储在 sql server 和 sqlite 中。 用户修改记录时更新sqlite日期修改, 同步运行时更新 sql server 上修改的日期。 在同步之前,我在 sqlServer 数据库中查询要更新的记录的修改日期,并将其与 if 语句中为该记录修改的 sqlite 的日期进行比较,然后为该记录运行更新存储过程或不运行
【讨论】:
以上是关于使用实体框架和存储过程进行并发检查的主要内容,如果未能解决你的问题,请参考以下文章