2

我正在开发我首先使用 EF 代码(v4.4)作为 ORM 和 SqlServer 作为数据库的应用程序。我还需要一个选项来从另一个具有相似数据结构的数据库类型中导入数据。在数据传输期间,我需要使用它们所具有的值传输标识列,以免破坏相关数据。

假设这是操作序列:

  1. 获取数据
  2. 将其转换为适合 EF 模型
  3. 将每个实体添加到 DbContext
  4. 保存更改

问题是它不会像原来那样插入标识值,因为我的主键被设置为标识列。

解决这个问题的方法之一是使用 IDENTITY_INSERT 命令,但它需要在同一个连接周期下与插入查询一起执行。连接周期是指在所有操作(IDENTITY_INSERT 和 INSERT INTO)期间不得关闭连接。

问题:ExecuteSqlCommand 会关闭连接,即使在调用它之前已显式打开它。

解决此问题的方法是不使用 EF 执行此任务,而是使用 ADO.NET SqlCommand。这样我们就可以更好地控制连接何时打开/关闭。

问题:如果我改变我的模型,我也需要改变导入查询,所以我需要在两个地方维护数据库结构。

任何建议如何使用 EF 实现这一目标?我不知道为什么 EF 团队决定在调用 ExecuteSqlCommand 后总是关闭连接。

4

2 回答 2

2

为了使用 EF DbContext,需要执行以下操作:

  • 使用 IObjectContextAdapter 打开连接
  • 使用 ObjectContext 的 ExecuteStoreCommand 打开/关闭 IDENTITY_INSERT
  • 在 DbContext 中有一个构造函数,您可以在其中进行数据转换时关闭 DatabaseGeneratedOption.Identity for PKs

至于性能,我发现最好的方法是对 X 记录进行批量更新,然后处理/重新创建上下文。此外,将 AutoDetectChangesEnabled 设置为 false

可以在此处找到有关性能的有趣阅读:

在实体框架中插入的最快方式

于 2012-09-03T10:15:09.533 回答
1

我认为正确的方法是放弃对标识值在源数据库和目标数据库中保持相同的要求。如果您将数据导入 EF 模型并保持关系不变,即创建一个父对象,然后正确添加其子对象,那么您的结构和关系将保持不变。

无论如何,您永远不会在查询中使用标识值,因此不必担心它们的值。

如果不出意外,这将更易于维护。

另一种选择是将 PK 列创建为常规可插入列,而不是自动生成。在 POCO 中,使用

<DatabaseGenerated(DatabaseGeneratedOption.None)>

装饰来实现这一点。

于 2012-08-29T05:54:43.473 回答