实体框架根据程序运行的位置创建不同的SQL

本文关键字:位置 创建 SQL 运行 框架 程序 实体 | 更新日期: 2023-09-27 18:17:48

我创建了一个小的c#控制台应用程序,它的唯一任务是解析xml文件并将结果放入数据库表中。我使用的是实体框架6.0和。net 4。

当我在本地计算机(Win7)上运行它时,一切都很好,但是当我在服务器(WS2008R2)上运行它时,它崩溃了。它是完全相同的文件只是复制/粘贴到服务器(即相同的数据库等)。

调试显示实体框架根据执行环境的不同创建了不同的sql查询。(见下文)

在本地计算机上(正常工作):

INSERT [dbo].[Accessories]([Id], [Name], [Category], [Price], [Description], [Phone_Id])
VALUES (@0, @1, @2, @3, @4, NULL)
@0: '1018' (Type = Int32)
@1: 'H141/A Headset Duoset' (Type = String, Size = -1)
@2: 'Headset Fixed Lines' (Type = String, Size = -1)
@3: '1563' (Type = Int32)
@4: 'H141/A DuoSet™, Plantronics headset.' (Type = String, Size = -1)
Executing 
Completed in 19 ms with result: 1

ON SERVER (Doesn ' t work):

INSERT [dbo].[Accessories]([Name], [Category], [Price], [Description], [Phone_Id])
VALUES (@0, @1, @2, @3, NULL)
SELECT [Id]
FROM [dbo].[Accessories]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
@0: 'H141/A Headset Duoset' (Type = String, Size = -1)
@1: 'Headset Fixed Lines' (Type = String, Size = -1)
@2: '1563' (Type = Int32)
@3: 'H141/A DuoSet™, Plantronics headset.' (Type = String, Size = -1)
Executing 
Failed in 1 ms with error: Cannot insert the value NULL into column 'Id', table 'Sales.dbo.Accessories'; column does not allow nulls. INSERT fails.
The statement has been terminated.

实际应用代码:

           try
           {
               XmlNodeList xNodeList = xDoc.SelectNodes("accessories/child::node()");
               foreach (XmlNode xNode in xNodeList)
               {
                   if (xNode.Name == "accessory")
                   {
                       var accessory = new Accessory();
                       accessory.Id = Convert.ToInt32(xNode.Attributes["id"].Value);
                       foreach (XmlNode childNode in xNode.ChildNodes)
                       {
                           if (childNode.Name == "name")
                           {
                               accessory.Name = childNode.InnerText;
                           }
                           if (childNode.Name == "category")
                           {
                               accessory.Category = childNode.InnerText;
                           }
                           if (childNode.Name == "description")
                           {
                               accessory.Description = childNode.InnerText;
                           }
                           if (childNode.Name == "price")
                           {
                               accessory.Price = Convert.ToInt32(childNode.InnerText);
                           }
                       }
                       _db.Add(accessory);
                   }
               }
               _db.SaveChanges();

sql server是MSSQL

我在这里有点迷路了。该怎么办?

实体框架根据程序运行的位置创建不同的SQL

我认为您的数据库服务器版本没有为您的主键(Id)设置身份规范为Yes。所以它不会自动生成一个Id号,因为你没有传递它,这就是为什么它在null Id上出错。

如果你使用Code First(我很确定你是),然后注意不同版本的实体框架(不是不同版本的SQL Server)使用微妙的不同规则映射类到表。依赖于EF版本的一件事是,整数属性Id是否自动映射到数据库中的IDENTITY列,而无需您的任何规范。如果您的数据库创建时使用Id作为常规的非标识列,并且您的代码更改了EF版本,因此现在需要一个标识列,那么事情就会中断。

解决方案是不要混合EF版本。选择一个版本,并坚持使用。确保该版本是您在本地计算机上使用的版本,也是您在服务器上使用的版本。确保实体框架dll的版本被复制到你的程序的安装目录,不要依赖全局安装的任何东西。

这就是我们问题的解决方案,我不知道为什么,但这里是:

我们忘了设置数据库初始化项。

Database.SetInitializer(new CustomContextInitializer());

现在调用:

public class CustomContextInitializer : IDatabaseInitializer<CustomProjectContext>
{        
    public void InitializeDatabase(CustomProjectContext context)
    {
        context.Database.Initialize(false);
    }
}

我猜实体或。net正在做一些自己的后台操作,如果这部分缺失,这就是为什么我们在不同的环境下有不同的SQL。