【问题标题】:Entity framework 3.5 create entities on the fly实体框架 3.5 动态创建实体
【发布时间】:2015-10-14 15:37:43
【问题描述】:

假设一个简单的数据模型由两个表组成,Book 和 Author,通过外键约束“Book.AuthorId = Author.Id”相关。

现在假设你有一些简单的书籍清单:

Title                          Author
---------------------------------------------------------
The Selfish Gene               Richard Dawkins
Why Is Sex Fun                 Jared Diamond
The Ancestors Tale             Richard Dawkins

如何在不进行大量往返 DB 的情况下导入这些文件?

我是 EF 的新手,但我认为它可以让我将实体添加到对象上下文中,然后即使它们尚未保存,它们也可以在该上下文中中使用。情况似乎并非如此。原则上,我这样做:

void Import()
{
    ctx = new Database();
    foreach (...)
    {
        Import(bookTitle, authorName);
    }

    ctx.SaveChanges();
}

void Import(string bookTitle, string authorName)
{
    var author = ctx.Authors.Single(a => a.Name == authorName);
    if (author == null)
    {
        author = new Author();
        author.Name = authorName;
        ctx.AddToAuthors(author);
    }

    var book = new Book();
    book.Author = author;

    ctx.AddToBooks(book);
}

但是 EF 永远找不到我已经添加的作者,所以它每次都会创建一个新作者。因此,Dawkins 的两本书与图中的两个不同作者对象相关,这当然是错误的。

接下来,在 SaveChanges 时,EF 设法插入第一条 Book 和 Author 记录,但随后在第二条记录上崩溃并出现 PRIMARY KEY VIOLATION,因为它尝试为每个对象使用 Id = 0。

System.Data.UpdateException: An error occurred while updating the entries.
See the InnerException for details. ---> 
  System.Data.SqlClient.SqlException: Violation of PRIMARY KEY 
  constraint 'PK_Book'. Cannot insert duplicate key in object 'dbo.Book'.

我试图在 MSSQL 中将 id 字段的定义更改为 INT IDENTITY(1,1),然后更新模型。让数据库定义键值总比让实体框架(或任何客户端)来做这件事要好。但这似乎根本不受支持。当我更新模型时,EF 似乎没有注意到我的键是 IDENTITY 列。它只是导致

System.Data.UpdateException: An error occurred while updating the entries. 
See the InnerException for details. ---> 
  System.Data.SqlClient.SqlException: Cannot insert explicit value for 
  identity column in table 'Book' when IDENTITY_INSERT is set to OFF.

无论我是否在列定义从“Id INT PRIMARY KEY”切换到“Id INT IDENTITY(1,1) PRIMARY KEY”之后更新模型,都会提供确切的症状,这让我怀疑微软甚至不记得思考身份列,尽管我希望我错了!

我意识到这里确实潜伏着多个问题,但由于 Entity Framework 中的任何内容都没有按预期工作,我选择将首要问题设为“鉴于此数据模型和要导入的这些数据,使用实体框架 3.5?”

请不要建议我改用 EF 4.0,因为这超出了我的控制范围。 :)

【问题讨论】:

    标签: c# .net sql-server entity-framework


    【解决方案1】:

    我的问题是基于一种误解——事实上,将对象添加到对象上下文而不保存确实会使它们在对象上下文中可用。

    真正发生的事情是:我正在使用 Reflection.Load 从 powershell 脚本触发 .net 程序集中的逻辑。当我在 .net 项目中进行更改、重建并 GAC 编辑它,然后重新运行我的 PowerShell 脚本时,我仍在运行旧代码。基本上来自 MyAssembly.dll 的代码链接到 powershell 会话中,所以当我重新运行脚本时,新版本的代码已部署到 GAC 并不重要......

    PK 违规是有道理的,因为我的代码没有为实体分配 ID,而且作者不止一个 - 我尝试使用 ID = 0 保存两者。

    “当 IDENTITY INSERT 关闭时无法插入显式值”现在也有意义了,因为我已经修改了我的数据库,但仍在运行假定应该插入 ID 的代码。

    简而言之,解决问题的方法是关闭我的 PowerShell 会话并启动一个新会话。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-22
      • 2011-07-29
      • 2011-07-15
      • 2013-03-15
      • 1970-01-01
      相关资源
      最近更新 更多