【问题标题】:What's the right way to save a record and keep the Primary Key using Entity Framework使用实体框架保存记录并保留主键的正确方法是什么
【发布时间】:2015-02-11 19:33:20
【问题描述】:

我正在尝试将数据播种到 Entity Framework 6 中新创建的数据库中。(或即时替换它)这是出于开发/测试目的,也可能用于未来的生产安装。我有几个从生产环境导出的 XML 文件,我需要这些文件才能进入开发和测试环境。要做到这一点,我需要将主键保留在查找表中。下面的代码显示了我最终是如何工作的。我花了一天时间寻找“正确的方法”来做这件事,遗憾的是最终硬编码了一个查询字符串,如代码所示。

public void Add(QuestionType questionType)
{
  using (var context = new SurveyFromDBContext())
  {
    using (var dbContextTransaction = context.Database.BeginTransaction())
    {
      try
      {
        context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [Kiosk].[QuestionTypes] ON");
        string sql = "INSERT INTO [KIOSK].[QuestionTypes] ( [Id], [Name], [Description]) VALUES (" +
          questionType.Id + ", '" + questionType.Name + "', '" + questionType.Description + "')";
        context.Database.ExecuteSqlCommand(sql);

        //context.QuestionTypes.Add(questionType);

        context.SaveChanges();
        context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [Kiosk].[QuestionTypes] OFF");
        dbContextTransaction.Commit();
      }
      catch (Exception e)
      {
        dbContextTransaction.Rollback();
      }
    }
  }
}

问题是:在 EF6 中,应该如何将记录插入到表中并保留主键?

请注意,由于遗留代码,主键需要能够自动更新,所以我不能这样做:

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }

除非可以以某种方式即时完成。

【问题讨论】:

  • 您是在问如何将自己的值插入到通常自动生成的字段中?
  • 您是否尝试将查询按原样转换为存储过程?至少这样你就可以保护自己免受 SQL 注入的影响。除此之外,我唯一的另一个想法是关闭数据库表上的标识(尽管这样做可能会导致无法预料的后果)
  • Claies:是的,这就是我想要做的。
  • user2366842:我想说我不能采用存储过程的方式,但我至少可以说我不想这样做。我试图弄清楚如何让实体框架进行插入但保留 PK 值。

标签: sql-server entity-framework entity-framework-6 sql-insert


【解决方案1】:

我不相信有什么好的方法可以做到这一点。你正在做的事情让我觉得更像是一个与 ETL 相关的任务,而不是一个 ORM 任务。

您所拥有的一个改进是这个(经过测试;与您上面描述的 DatabaseGeneratedOption 结合使用)。我认为没有必要关闭 identity_insert ;无论如何,它在更新后恢复为关闭:

        using ( var context = new YourEntities() )
        {
            var connection = (SqlConnection)context.Database.Connection;
            using ( var cmd = new SqlCommand( "set identity_insert QuestionTypes on", connection) )
            {
                connection.Open();
                cmd.ExecuteNonQuery();
            }

            var qt = new QuestionType { id = 2, name = "test" };
            context.QuestionTypes.Add( qt);
            context.SaveChanges();
        }

【讨论】:

  • 您可能正确地认为这是 ETL 工作的 dudeNumber4。我周围没有数据库人员为我做这项工作,所以我试图通过代码来做。 (我们现在遇到了数据库环境问题,所以我试图让这个过程不可知。在过去的几个月里,我不得不在桌面机器上使用本地数据库或 SQL Server 2008r2,因为没有'不是开发或测试环境。)我也在尝试进行设置,以便人们可以手动修改文件以创建测试场景的设置。
  • dudeNumber4:当我注释掉插入的行并使用当前注释掉的行“context.QuestionTypes.Add(questionType);”然后实体框架接管并让数据库生成自己的 ID。我的研究表明,原因是 EF 中的 .Add 被包装在它自己的事务中,而我围绕它创建的工作被忽略了。
  • @user1582732:将模型中的列标记为 DatabaseGeneratedOption.None 只是告诉模型对数据库的期望。当查询被提交到数据库时,无论您从哪里提交查询,它都会做它总是做的事情。上面的 sn-p 使用 EF 好像 id 不是身份,但是不,如果没有 identity_insert 命令,它将永远无法工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
相关资源
最近更新 更多