【发布时间】:2016-05-25 21:25:29
【问题描述】:
我正在使用 Entity Framework 6 Code First。要使用我的数据库,我需要一个存储过程。每当创建数据库时,都需要创建此存储过程。
编辑:存储过程的原因写在这篇文章的末尾。
从 Stackoverflow 我知道如何创建存储过程以及如何调用它。我的问题是我在哪里创建它?
我的第一直觉是在 DbContext.OnModelCreating。每当创建模型时都会调用此函数。在这个函数中,您将告诉模型构建者模型应该是什么样子。
唉,在这个函数中我还不能使用 DbContext。有一些函数可以覆盖插入/更新/删除过程,但我需要一个不同的过程。
我考虑在 DropCreateDataBaseIfModelChanges 的 Seed 函数中添加该函数,但这会阻止我的 DbContext 的用户使用他们自己想要的数据来种子数据库。
DbMigrations 似乎是为了将现有数据库迁移到较新的数据库而开发的。在创建数据库的第一个版本时不使用。
那么在哪里创建存储过程呢?
编辑。我需要存储过程的原因如下
我的服务收到通知,说客户今天在某事上花钱了。我需要记住每位客户的总天数。
- 如果客户在日期没有花费任何费用,也就是说,如果不存在带有 (customerId, date) 的记录,则插入带有花费值的记录
- 如果客户已经在 datae 上花费了一些东西,即如果已经存在带有 (customerId, date) 的记录,则将花费的值添加到记录中的值中
类似这样的:
public void InsertOrAdd(int customerId, DateTime date, decimal value)
{
using (var dbContext = CreateContext())
{
var retrievedRecord = dbContext.Find(...)
if (retrievedRecord == null)
{
InsertRecord(customerId, date, value);
}
else
{
retrievedRecord.Value += value;
dbContext.SaveChanges();
}
}
}
问题是在我的查找之后,其他人可能已经插入了一条记录。在那种情况下,我应该增加价值。相反,将有两条记录。或者,当我正在处理现有记录并添加值时,其他人可能会处理相同的现有记录。因此,应该在数据库中使用类似
的语句添加值update [CustomerSpends]
Set [SpentValue] = [SpentValue] + @Value
Where [CustomerId] = @CustomerId and [SpentDate] = @SpentDate
第二次修改 正如* Ivan Yuriev* 已经提到的,上述问题可以使用交易来解决。但是,我仍然会遇到添加支出的问题。
如果这将是一个 3 步过程,就像 Ivan 建议的那样,那就是:
- 获取现有记录
- 将花费的值添加到记录中的总值中
- 保存更改
这样做的缺点是我总是需要两次往返数据库。此外,我还得到了一系列客户支出。如果其中任何一个处理失败,则所有内容都需要回滚。即使使用事务也可能存在竞争条件
最高的Transaction Isolation level (MSDN) 被读提交。
已提交阅读 指定语句不能读取已被其他事务修改但未提交的数据。这可以防止脏读。当前事务中各个语句之间的其他事务可能会更改数据,从而导致不可重复读取或幻像数据。
当使用上面定义的三步过程时,我获取记录 X,总花费值为 5.00 美元。虽然我将 $3 添加到总数中,但其他人也可以获取记录 X,因为它还没有被修改。另一个人收到了总计 5 美元的记录。在我添加后,总值变为 8 美元。我使用 SaveChanges 更新该值并继续处理其他记录。过了一会儿,我提交了我的更改。仍然有$ 5记录的另一个进程应该添加$ 2,以$ 7的值结束,而最终结果应该是$ 10
使用事务不能阻止其他人读取数据。因此获取-增值-更新应该在一个SQL语句中完成
【问题讨论】:
-
实体框架代码优先旨在使思维过程远离使用存储过程/sql。数据库迁移实际上用于表示您的数据库,通常在启动新数据库时使用,但可以通过逆向工程的任何一种方式使用。此代码表示与播种一起用于拆除数据库并根据环境需要将其备份。您需要 SP 是否有特定原因?
-
类似:记住每位客户每天的成本。如果客户今天已经产生了成本,则添加新值,否则创建今天的成本并使用该值进行初始化。如果我确实查找并检测到它不存在,我可以添加,但与此同时其他人可能也做了同样的事情。因此,这必须在一个 SQL 语句中。可能类似于合并
-
为什么不用事务来避免别人往数据库中插入记录呢?
标签: c# entity-framework stored-procedures