你可以使用Entity Framework 4.1 Code第一种方法创buildsql视图/存储过程

entity framework4.1代码首先很好地创build表和关系。 是否有可能使用代码优先的方法创buildSQL视图或存储过程? 任何关于这个指针将高度赞赏。 非常感谢!

EF代码优先方法期望在数据库中没有逻辑。 这意味着没有存储过程和数据库视图。 由于那个代码优先的方法没有提供任何机制来为你自动生成这样的结构。 如果它意味着产生逻辑,它怎么能这样做呢?

您必须通过手动执行创build脚本将它们自己创build到自定义数据库初始化程序中 。 我不认为这个自定义SQL结构可以通过SQL迁移来处理。

我们在entity framework代码优先迁移中支持存储过程。 我们的方法是创build一个文件夹来保存.sql文件(〜/ Sql /例如)。 在创build和删除存储过程的文件夹中创build.sql文件。 例如Create_sp_DoSomething.sqlDrop_sp_DoSomething 。 由于SQL以批处理方式运行并且CREATE PROCEDURE..必须是批处理中的第一条语句,因此请使CREATE PROCEDURE...文件中的第一条语句。 另外,在DROP...之后不要放GO 。 添加一个资源文件到你的项目,如果你还没有。 将.sql文件从解决scheme资源pipe理器拖到资源devise器的“文件”视图中。 现在创build一个空的迁移( Add-Migration SomethingMeaningful_sp_DoSomething )并使用:

 namespace MyApplication.Migrations { using System; using System.Data.Entity.Migrations; public partial class SomethingMeaningful_sp_DoSomething : DbMigration { public override void Up() { this.Sql(Properties.Resources.Create_sp_DoSomething); } public override void Down() { this.Sql(Properties.Resources.Drop_sp_DoSomething); } } } 

〜/ SQL / Create_sp_DoSomething.sql

 CREATE PROCEDURE [dbo].[sp_DoSomething] AS BEGIN TRANSACTION -- Your stored procedure here COMMIT TRANSACTION GO 

〜/ SQL / Drop_sp_DoSomething.sql

 DROP PROCEDURE [dbo].[sp_DoSomething] 

乍看之下,我真的很喜欢卡尔G的方法,但它涉及到大量的手动交互。 在我的场景中,我总是删除所有存储过程,视图…并在数据库发生更改时重新创build它们。 这样,我们确信一切都是最新的版本。

通过设置下面的初始化程序来进行娱乐:

 Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>()); 

然后,我们的种子方法将在移动准备就绪时被调用

 protected override void Seed(DeploymentLoggingContext context) { // Delete all stored procs, views foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sql\\Seed"), "*.sql")) { context.Database.ExecuteSqlCommand(File.ReadAllText(file), new object[0]); } // Add Stored Procedures foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sql\\StoredProcs"), "*.sql")) { context.Database.ExecuteSqlCommand(File.ReadAllText(file), new object[0]); } } 

SQL语句存储在* .sql文件中以便于编辑。 确保你的文件的“生成行动”设置为“内容”和“复制到输出目录”设置为“始终复制”。 我们查找文件夹并执行里面的所有脚本。 不要忘记在SQL中排除“GO”语句,因为它们不能用ExecuteSqlCommand()来执行。

我目前的目录布局如下:

Project.DAL
+迁移
+ Sql
++种子
+++ dbo.cleanDb.sql
++ StoredProcs
+++ dbo.sp_GetSomething.sql

现在你只需要在文件夹中放置额外的存储过程,一切都会得到适当的更新。

它看起来是不好logging,但是现在你可以使用AlterStoredProcedure , CreateStoredProcedure , DropStoredProcedure , MoveStoredProcedure , RenameStoredProcedure在entity framework6中执行一些存储过程操作。我还没有尝试过它们,所以还不能给出如何使用它们。

为了扩展bbodenmiller的答案 ,在entity framework6中, DbMigration类具有诸如AlterStoredProcedure之类的方法,这些方法允许修改存储过程,而不必一直拖到原始SQL。

下面是一个Up()迁移方法的示例,该方法改变了一个名为EditItem的现有SQL Server存储过程,它分别接受三个types为intnvarchar(50)smallmoney

 public partial class MyCustomMigration : DbMigration { public override void Up() { this.AlterStoredProcedure("dbo.EditItem", c => new { ItemID = c.Int(), ItemName = c.String(maxLength:50), ItemCost = c.Decimal(precision: 10, scale: 4, storeType: "smallmoney") }, @" (Stored procedure body SQL goes here) " } //... } 

在我的机器上,此迁移脚本生成以下SQL:

 ALTER PROCEDURE [dbo].[EditItem] @ItemID [int], @ItemName [nvarchar](50), @ItemCost [smallmoney] AS BEGIN (Stored procedure body SQL goes here) END 

emp的devise就像一个冠军! 我使用他的模式,但我也映射存储过程在我的DbContext类,允许只是调用这些上下文方法,而不是使用SqlQuery()直接从我的存储库调用过程。 随着应用程序的增长,事情会变得有些毛病,我在我的Seed方法中创build了一个检查,确保实际的存储过程参数计数匹配映射方法的参数计数。 我也更新了提及的DROP循环。 我只需读取每个sql文件的第一行,并用DROPreplaceCREATE (只要确保第一行始终只是CREATE PROCEDURE ProcName ),而不必为drop语句保留一个单独的文件夹/文件。 这样,每次运行Update-Database时,我的StoredProcs文件夹中的所有过程都会被删除并重新创build。 如果过程是新的,则放置也被包装在try-catch块中。 为了使程序参数计数起作用,您需要确保在tsql周围包装BEGIN/END块,因为文件的每一行都被读取到BEGIN。 还要确保每个sp参数都在新的行上。

  // Drop Stored Procs foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\DataContext\\SiteMigrations\\StoredProcs"), "*.sql")) { // Try to drop proc if its already created // Without this, for new procs, seed method fail on trying to delete try { StreamReader reader = new StreamReader(file); // Read first line of file to create drop command (turning CREATE [dbo].[TheProc] into DROP [dbo].[TheProc]) string dropCommand = reader.ReadLine().Replace("CREATE", "DROP"); context.Database.ExecuteSqlCommand(dropCommand, new object[0]); } catch { } } // Add Stored Procs foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\DataContext\\SiteMigrations\\StoredProcs"), "*.sql")) { // File/Proc names must match method mapping names in DbContext int lastSlash = file.LastIndexOf('\\'); string fileName = file.Substring(lastSlash + 1); string procName = fileName.Substring(0, fileName.LastIndexOf('.')); // First make sure proc mapping in DbContext contain matching parameters. If not throw exception. // Get parameters for matching mapping MethodInfo mi = typeof(SiteContext).GetMethod(procName); if (mi == null) { throw new Exception(String.Format("Stored proc mapping for {0} missing in DBContext", procName)); } ParameterInfo[] methodParams = mi.GetParameters(); // Finished getting parameters // Get parameters from stored proc int spParamCount = 0; using (StreamReader reader = new StreamReader(file)) { string line; while ((line = reader.ReadLine()) != null) { // If end of parameter section, break out if (line.ToUpper() == "BEGIN") { break; } else { if (line.Contains("@")) { spParamCount++; } } } } // Finished get parameters from stored proc if (methodParams.Count() != spParamCount) { string err = String.Format("Stored proc mapping for {0} in DBContext exists but has {1} parameter(s)" + " The stored procedure {0} has {2} parameter(s)", procName, methodParams.Count().ToString(), spParamCount.ToString()); throw new Exception(err); } else { context.Database.ExecuteSqlCommand(File.ReadAllText(file), new object[0]); } } 

请享用!

正如Ladislav所指出的那样, DbContext通常倾向于最小化数据库中的逻辑,但可以使用context.Database.ExecuteSqlCommand()context.Database.SqlQuery()来执行自定义SQL。