C# seed上的EXECUTESQLSCOMMAND使用EntityFramework创建触发器引发SqlException
我试图在Entity Framework 6.0.2和.Net 4的ContextInitializer中创建一个触发器,使用Seed()方法更新文档编号。当我单独运行SQL时,就会创建触发器;在上下文初始化期间,将抛出一个SqlException,说明: “触发器”一词附近的语法不正确 我的sql脚本(包含在/sql/CreateOrderNumber.sql中)是: 下面的代码将重新创建错误:C# seed上的EXECUTESQLSCOMMAND使用EntityFramework创建触发器引发SqlException,c#,sql,entity-framework,entity-framework-6,C#,Sql,Entity Framework,Entity Framework 6,我试图在Entity Framework 6.0.2和.Net 4的ContextInitializer中创建一个触发器,使用Seed()方法更新文档编号。当我单独运行SQL时,就会创建触发器;在上下文初始化期间,将抛出一个SqlException,说明: “触发器”一词附近的语法不正确 我的sql脚本(包含在/sql/CreateOrderNumber.sql中)是: 下面的代码将重新创建错误: using System.ComponentModel.DataAnnotations; usin
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
namespace TriggerCreationTest
{
class Program
{
static void Main(string[] args)
{
// Create the context, add an order, and save...
using (var context = new Context())
{
context.Orders.Add(new Order());
context.SaveChanges();
}
}
}
public class Context : DbContext
{
public Context() : base("TestDatabase")
{
Database.SetInitializer<Context>(new ContextInitializer());
}
public DbSet<Order> Orders { get; set; }
}
public class ContextInitializer : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
// Get the file and read the text
var execPath = Assembly.GetExecutingAssembly().Location;
var createOrderNumPath = Path.Combine(execPath, @"..\SQL\CreateOrderNumber.sql");
var sql = File.ReadAllText(createOrderNumPath);
// Execute the CREATE TRIGGER on the database.
var emptyparams = new SqlParameter[] { new SqlParameter() };
context.Database.ExecuteSqlCommand(sql, emptyparams);
base.Seed(context);
}
}
public class Order
{
public Order() { }
[Key]
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string DocNumber { get; set; }
}
}
使用System.ComponentModel.DataAnnotations;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Data.Entity;
使用System.Data.SqlClient;
使用System.IO;
运用系统反思;
命名空间触发器CreationTest
{
班级计划
{
静态void Main(字符串[]参数)
{
//创建上下文,添加订单,然后保存。。。
使用(var context=new context())
{
context.Orders.Add(neworder());
SaveChanges();
}
}
}
公共类上下文:DbContext
{
公共上下文():基(“TestDatabase”)
{
SetInitializer(新的ContextInitializer());
}
公共数据库集命令{get;set;}
}
公共类ContextInitializer:DropCreateDatabaseAlways
{
受保护的覆盖无效种子(上下文)
{
//获取文件并读取文本
var execPath=Assembly.GetExecutingAssembly().Location;
var createOrderNumPath=Path.Combine(execPath,@..\SQL\CreateOrderNumber.SQL”);
var sql=File.ReadAllText(createOrderNumPath);
//在数据库上执行CREATE触发器。
var emptyparams=new SqlParameter[]{new SqlParameter()};
context.Database.ExecuteSqlCommand(sql,emptyparams);
种子(上下文);
}
}
公共阶级秩序
{
公共秩序(){}
[关键]
公共int Id{get;set;}
[数据库生成(DatabaseGeneratedOption.Computed)]
公共字符串DocNumber{get;set;}
}
}
此时,我已尝试根据web上的各种来源重新编写创建触发器脚本,但没有成功地使其运行。在解决此问题并关注其他项目后,我返回查看升级到EntityFramework 6.1.0是否会有所不同。它没有 然而,我确实发现了我的错误。我将一个空的SqlParameter传递给SqlCommand,这导致它失败。如果改为将SqlParameter数组更改为不包含任何元素:
public class ContextInitializer : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
// Get the file and read the text
var execPath = Assembly.GetExecutingAssembly().Location;
var createOrderNumPath = Path.Combine(execPath, @"..\SQL\CreateOrderNumber.sql");
var sql = File.ReadAllText(createOrderNumPath);
// Execute the CREATE TRIGGER on the database.
// CHANGE emptyparams TO CONTAIN NO ELEMENTS
var emptyparams = new SqlParameter[] { };
context.Database.ExecuteSqlCommand(sql, emptyparams);
base.Seed(context);
}
}
公共类ContextInitializer:DropCreateDatabaseAlways
{
受保护的覆盖无效种子(上下文)
{
//获取文件并读取文本
var execPath=Assembly.GetExecutingAssembly().Location;
var createOrderNumPath=Path.Combine(execPath,@..\SQL\CreateOrderNumber.SQL”);
var sql=File.ReadAllText(createOrderNumPath);
//在数据库上执行CREATE触发器。
//将emptyparams更改为不包含任何元素
var emptyparams=newsqlparameter[]{};
context.Database.ExecuteSqlCommand(sql,emptyparams);
种子(上下文);
}
}
命令按预期执行并创建触发器。触发器是否已存在?否,在我的原始项目中,我运行了一个DROP触发器(已成功运行),在创建触发器脚本之前运行脚本,但在上面的示例中,每次初始化上下文时都会重新创建数据库。您是否尝试将触发器作为一个大字符串从文件中读取?反之亦然:读取.sql字符串后,设置断点并检查读取的字符串。它是否仍然有效,或者f.e.是否添加/缺少字符?@Serv,根据您的建议尝试读取单个长字符串,但仍然得到相同的SqlException。从文件中读取字符串后,检查该字符串看起来与var sql=@“多行上的somestring”格式的字符串输入相同;。
public class ContextInitializer : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
// Get the file and read the text
var execPath = Assembly.GetExecutingAssembly().Location;
var createOrderNumPath = Path.Combine(execPath, @"..\SQL\CreateOrderNumber.sql");
var sql = File.ReadAllText(createOrderNumPath);
// Execute the CREATE TRIGGER on the database.
// CHANGE emptyparams TO CONTAIN NO ELEMENTS
var emptyparams = new SqlParameter[] { };
context.Database.ExecuteSqlCommand(sql, emptyparams);
base.Seed(context);
}
}