EF 6代码优先与自定义存储过程

时间:2014-04-25 20:00:38

标签: c# sql-server asp.net-mvc entity-framework stored-procedures

我正在使用Code-First方法创建一个MVC 5应用程序,但我还在SQL Server数据库上创建了一些存储过程,有没有办法在创建数据库时在c#中生成这些存储过程,也许通过执行sql脚本,如果是这样,我应该在哪里这样做?

3 个答案:

答案 0 :(得分:4)

我会使用代码迁移。

您可以在Nuget Package Manager中输入

设置空白迁移
add-migration AddMyStoredProcedure

这应该生成一个像这样的空类

public partial class AddMyStoredProcedure : DbMigration
{
    public override void Up()
    {
    }

    public override void Down()
    {
    }
}

您需要做的就是添加您的存储过程(请记住在Down方法中删除存储过程,以防将来需要回滚迁移)。

    public partial class AddMyStoredProcedure : DbMigration
{
    public override void Up()
    {
        Sql(@"
            CREATE PROCEDURE dbo.GetMyAddress
            AS
            SELECT * FROM Person.Address");
    }

    public override void Down()
    {
        Sql("DROP PROCEDURE dbo.GetMyAddress");
    }
}

最后更新您的数据库

update-database

答案 1 :(得分:4)

迟到的答案,但也许有人会得到这个问题的答案

我的项目中有很多viewsfunctions以及stored procedures来处理,我使用的解决方案如下:

  1. 在项目中创建一个sql文件,以删除所有视图功能过程,如果它们存在,例如,将其称为drop.sql
  2. 为每个viewfunction以及stored procedure创建项目中的单独sql文件。
  3. 将所有sql文件标记为Embedded Resource,右键单击文件,然后单击属性,然后选择Build Action,选择Embedded Resource
      

    YourFile.sql =>右键单击=>属性=>构建操作,选择嵌入式资源

  4. 在迁移种子功能中,使用ExecuteSqlCommand,您需要一种方法来阅读这些文件以及所需的所有代码。
  5. drop.sql结构

    -- your views
    if object_id('dbo.[YourViewName1]') is not null
        drop view dbo.[YourViewName1]
    if object_id('dbo.[YourViewName2]') is not null
        drop view dbo.[YourViewName2]
    -- your functions 
    if object_id('dbo.[Function1]') is not null
        drop function dbo.[Function1]
    if object_id('dbo.[Function2]') is not null
        drop function dbo.[Function2]
    -- your procedures
    if object_id('dbo.[Procedure1]') is not null
        drop procedure dbo.[Procedure1]
    if object_id('dbo.[Procedure2]') is not null
        drop procedure dbo.[Procedure2]
    

    view.sql或function.sql或procedure.sql结构

    create view View1 
    as
      select Field1,Field2,...Fieldn
      from Table1
      inner join Table2 on Id1 = FId2  
      inner join TableN on IdI = IdJ
    

    迁移种子方法

      

    我假设您在 Sql 文件夹中创建了所有sql文件    在项目中迁移文件夹

    protected override void Seed(YourContext context)
    {
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.drop.sql"));
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.view1.sql"));
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.view2.sql"));
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.function1.sql"));
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.function2.sql"));
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.procedure1.sql"));
        context.Database
                .ExecuteSqlCommand(Load("YourProject.Migrations.Sql.procedure2.sql"));
    }
    

    最后加载方法

    private static string Load(string name)
    {
        var assembly = Assembly.GetExecutingAssembly();
    
        using (Stream stream = assembly.GetManifestResourceStream(name))
        using (StreamReader reader = new StreamReader(stream))
        {
            string result = reader.ReadToEnd();
            return result;
        }
    }
    
      

    这个解决方案的好处是它每次都会运行,你会的   确保如果有任何问题(例如,一段时间后您更改了字段名称或删除了在视图中使用的表或   功能或程序没有记住您必须更新您的程序,您将收到错误,如果您启用了自动迁移,则可以修复。)

    希望这会对你有所帮助

答案 2 :(得分:0)

您可能需要使用迁移来处理它。可以找到一个好看的解决方案https://stackoverflow.com/a/15171900/119262。使用资源,但我相信如果你不想沿着资源路径走,你可以用同样的方式从你的.sql文件中读出文本。