2016-05-24 104 views
0

我使用实体框架6 Code First。要使用我的数据库,我需要一个存储过程。无论何时创建数据库,都需要创建该存储过程。EF6:在哪里创建存储过程?

编辑:存储过程的原因写在这篇文章的末尾。

从Stackoverflow我知道如何创建一个存储过程以及如何调用它。我的问题是我在哪里创建它?

我的第一个直觉是在DbContext.OnModelCreating。这个函数在模型创建时被调用。在这个函数中,你会告诉模型构建者模型应该是什么样的。

唉,在这个函数中我还不能使用DbContext。有重写插入/更新/删除过程的功能,但我需要一个不同的过程。

我认为在DropCreateDataBaseIfModelChanges的函数中添加函数,但是会阻止我的DbContext的用户使用他们自己想要的数据为数据库播种。

DbMigrations似乎开发用于将现有数据库迁移到较新的数据库。在创建数据库的第一个版本时不要使用。

那么在哪里创建存储过程?


编辑。我需要一个存储过程的原因如下:

我的服务收到客户今天花钱购买东西的通知。我需要记住每个客户的一天总计。

  • 如果客户没有日期,这是如果与(客户ID,日期)没有记录存在,插入一条记录,与耗费值
  • 它的客户已经花了东西就花了什么datae,这是如果与(客户ID,日期)的记录已经存在,则耗费值

添加一些值的记录是这样的:

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 

第二编辑 为*伊万尤里耶夫*使用事务已经提到以上可以解决。但是我仍然会遇到添加花费的问题。

如果这将是一个3步骤的过程,像伊万所暗示的,它会像:

  • 取现有记录
  • 添加spentValue总价值在记录
  • 的SaveChanges

这有缺点,我总是需要两次往返数据库。除此之外,我还得到一系列顾客花费。如果其中任何一个处理失败,则需要回滚所有内容。即使使用交易,也有可能存在竞争条件

最高Transaction Isolation level (MSDN)被提交。

READ COMMITTED 指定语句不能读取已被修改但未被其他事务提交的数据。这可以防止脏读。数据可以通过当前事务中单个语句之间的其他事务进行更改,从而导致不可重复读取或幻影数据。

当使用上面定义的三步过程时,我获取记录X,总消耗值为5.00美元。虽然我总共增加了3美元,但其他人也可以获取记录X,因为它尚未修改。另一个收到总额为$ 5的记录。添加后,总价值变为$ 8。我使用SaveChanges更新该值并继续记录其他记录。一段时间后,我承诺我的变化。另一个仍然有$ 5记录的进程应该增加$ 2,以$ 7结尾,而最终结果应该是$ 10

使用事务不能阻止其他人读取数据。因此,取 - 增值 - 更新应该在一个SQL语句来完成创建一个空白迁移管理和添加在截至方法您的存储过程和删除该存储过程逆作法

+0

实体框架代码优先是为了使思想过程远离使用存储过程/ sql。数据库迁移实际上用于表示数据库,通常在启动新数据库时使用,但可以通过逆向工程使用。此代码表示与播种一起用于拆除数据库并根据环境需要进行备份。是否有你需要SP的具体原因? –

+0

类似于:记住每位顾客每天的费用。如果客户今天已经花费了成本,那么添加新的价值,否则创建今天的成本并用该值进行初始化。如果我找到并检测到它不在那里,我可以添加,但同时其他人也可能做到这一点。因此这必须在一个SQL语句中。可能类似于合并 –

+0

为什么不使用事务来避免其他人在数据库中插入记录? –

回答

1

的最佳方式。

这将工作。

1)通过在包管理器控制台运行命令

add-migration 'SomeName' -IgnoreChanges 

添加空白迁移它将创建迁移文件

2)现在加入您的存储过程,在向上和向下

删除存储过程
public partial class SomeName: DbMigration 
    { 
     public override void Up() 
     { 
      Sql(@"Add Command For StoredProcedure"); 

     } 

     public override void Down() 
     { 
      Sql(@"Drop Command for Stored Procedure") 
     } 
    } 

在Down方法中添加Drop同样重要。

1

不通。我发现代码第一次迁移是非常有限的,只有那些对SQL服务器概念和功能缺乏深刻理解的人才会感觉舒适。

我去的方式是:

  • 我维护一个主数据库和架构同步到架构项目。
  • 定期生成增量脚本,然后我手动维护。
  • 我有一个库,它根据存储在扩展属性中的数据库的版本号,根据需要应用增量脚本。

不使用迁移的原因很简单 - 您最终不得不提交太多的SQL脚本。迁移甚至不处理诸如正确的完全配置的索引(过滤索引),不知道存储过程,触发器和视图,无法处理分区表,无法有效处理可能需要临时表的数据迁移在表格布局改变时存储数据。因为我不处理琐碎的数据库,所以我几乎每天都需要几乎所有这些功能。

说出完整的真相 - 我从来没有发现代码,即使是一种有效的方法。这太容易出错了。唯一更糟糕的是,首先使用EF工具的数据库 - 主要是因为edmx设计器太烂了,完全无法处理更新。第三方编辑可用,但他们工作。

+0

我最近一直在想同样的事情......你会推荐哪些第三方工具? – Jcl

+0

Devart拥有另一位编辑,他在MS给予我们的未完成编辑器之前突飞猛进。 – TomTom