2011-12-30 17 views

回答

4

实体框架不知道给定的视图是否可更新或不可更新,因此它添加了该元素以防止框架尝试针对不可更新的视图生成查询。

如果您的视图是可更新的,您可以简单地将您的视图的EntitySet定义中的元素从您的.edmx的StorageModel部分内部移除,并且正常的更新处理将与任何其他表一样工作。

如果您的视图不可更新,则必须通过“修改函数映射”自己提供更新逻辑。修改函数映射调用您的.edmx的StorageModel部分中定义的函数。该函数可能包含数据库中存储过程的名称和参数,或者您可以使用“定义命令”来直接在.edmx的StorageModel部分的函数定义中写入插入,更新或删除语句。

在这两个选项中,如果你的视图是可更新的(它听起来可能是这样),最简单的就是删除设计者插入的内容。

+1

确认,需要在你的桌上PK(一个复合PK将做)。删除定义查询会让事情变得更糟。 – StuartLC 2012-08-06 07:12:16

+0

我有这个问题,但如果我从EDMX中删除DefiningQuery部分,下一次我从数据库更新模型时会重新生成此部分? – Jerry 2013-06-05 17:24:35

25

确保您的表具有主键!

3

更新:最近我得到了一些赞扬,所以我想让人们知道我给出的建议不是最好的。由于我最初开始关注在旧的无钥匙数据库上使用Entity Framework,我逐渐意识到,BY FAR可以做的最好的事情是通过反向代码优先做到这一点。关于如何做到这一点,有几篇很好的文章。只需遵循它们,然后当您想为其添加密钥时,使用数据注释来“伪造”密钥。

例如,假设我知道我的表Orders,虽然它没有主键,但确保每个客户只有一个订单号。由于这些都是餐桌上的前两列,我设置代码第一类是这样的:

[Key, Column(Order = 0)] 
    public Int32? OrderNumber { get; set; } 

    [Key, Column(Order = 1)] 
    public String Customer { get; set; } 

通过这样做,你基本上是伪造的EF,以为有由聚集键OrderNumber和Customer。这将允许您在无钥匙桌上插入,更新等。

如果你不太熟悉反向代码优先,那么去实体框架代码优先找一个好的教程。然后,一旦你对此感到满意,就去找一个关于反向代码优先(Code First)和现有数据库的代码。然后回到这里再看看我的重要建议。 :)

原来的答案

第一:正如其他人所说,最好的选择是一个主键添加到表。句号。如果你能做到这一点,请不要再阅读。

但是,如果你不能,或只是恨自己,有没有办法做到这一点,主键。基本上,我们要做的是对实体框架说谎,并告诉它有一个主键。

在我的情况下,我正在使用遗留系统(AS400上的最初平面文件移植到Access,然后移植到T-SQL)。所以我必须找到一个方法。这是我的解决方案。以下内容适用于我使用Entity Framework 6.0(NuGet截至撰写本文时的最新版本)。

  1. 右键单击解决方案资源管理器中的.edmx文件。选择“打开方式...”,然后选择“XML(文本)编辑器”。我们将在这里手动编辑自动生成的代码。

  2. 查找这样一行:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. 从最终删除store:Name="table_name"

  4. 变化store:Schema="whatever"Schema="whatever"

  5. 的外观,线下,找到<DefiningQuery>标签。它会有一个很大的选择陈述。删除标签和它的内容。现在

  6. 你行应该是这个样子:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. 我们还有别的改变。通过你的文件,去寻找这样的:
    <EntityType Name="table_name">

  8. 最近你可能会看到一些评论文字警告你,它没有一个主键识别,从而键已被推断和定义是读 - 仅表/视图。您可以保留或删除它。我删了它。

  9. 以下是<Key>标签。这是Entity Framework将用于插入/更新/删除的内容。所以请确保你做到了这一点。该标签中的属性(或属性)需要指明一个唯一可识别的行。例如,假设我知道我的表orders,虽然它没有主键,但确保每个客户只有一个订单号。

所以我的样子:

<EntityType Name="table_name"> 
       <Key> 
       <PropertyRef Name="order_numbers" /> 
       <PropertyRef Name="customer_name" /> 
       </Key> 

严重的是,不这样做是错误的。假设即使不应该有重复,但有两行以相同的订单号和客户名称进入我的系统。 Whooops!这就是我不使用密钥所得到的结果!所以我使用实体框架来删除一个。因为我知道重复是今天唯一的订单,所以我这样做:

var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today); 
myModel.orders.Remove(duplicateOrder); 

猜猜是什么?我刚刚删除了重复和原来的!这是因为我告诉Entity Framework order_number/cutomer_name是我的主键。所以,当我告诉它删除duplicateOrder,它在后台做的是一样的东西:

DELETE FROM orders 
WHERE order_number = (duplicateOrder's order number) 
AND customer_name = (duplicateOrder's customer name) 

有了这样的警告......你现在应该好走!