更新:我最近对此有一些反对意见,所以我想让人们知道我在下面给出的建议不是最好的。自从我最初开始考虑在旧的无密钥数据库上执行Entity Framework以来,我逐渐认识到BY FAR可以做的最好的事情就是先进行反向代码。关于如何执行此操作的文章不错。只需跟随它们,然后在要向其添加密钥时,使用数据注释“伪造”密钥。
例如,假设我知道我的表Orders
虽然没有主键,但可以确保每个客户只有一个订单号。由于这些是表的前两列,因此我将代码优先类设置为如下所示:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
通过这样做,您基本上是在使EF假装EF认为存在由OrderNumber和Customer组成的集群密钥。这将允许您在无密钥表上进行插入,更新等操作。
如果您不太熟悉执行反向代码优先,请查找关于Entity Framework Code First的很好的教程。然后在Reverse Code First上找到一个(正在使用现有数据库执行Code First)。然后回到这里,再次查看我的主要建议。:)
原始答案:
第一:正如其他人所说,最好的选择是向表添加主键。句号 如果可以这样做,请继续阅读。
但是,如果您不能或者只是讨厌自己,那么有一种方法可以在没有主键的情况下做到这一点。
就我而言,我正在使用旧系统(最初是将AS400上的平面文件移植到Access,然后移植到T-SQL)。所以我必须找到一种方法。这是我的解决方案。以下内容使用Entity Framework 6.0(在撰写本文时,它是NuGet上的最新版本)为我工作的。
在解决方案资源管理器中右键单击您的.edmx文件。选择“打开方式...”,然后选择“ XML(文本)编辑器”。我们将在这里手动编辑自动生成的代码。
寻找这样的一行:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
store:Name="table_name"
从末端移开。
更改store:Schema="whatever"
为Schema="whatever"
在该行下面查找并找到<DefiningQuery>
标签。它将有一个很大的选择语句。删除标签及其内容。
现在您的行应如下所示:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
我们还有其他改变。浏览您的文件并找到以下内容:
<EntityType Name="table_name">
在附近,您可能会看到一些注释文本,警告您未标识主键,因此已推断出该键,并且该定义是只读表/视图。您可以保留或删除它。我删除了它。
以下是<Key>
标签。这就是Entity Framework将用于执行插入/更新/删除的操作。因此,请确保您这样做是正确的。该标记中的一个或多个属性需要指示唯一可识别的行。例如,假设我知道我的表orders
虽然没有主键,但可以确保每个客户只有一个订单号。
所以我的看起来像:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
认真地,不要做错这个。假设即使永远都不会重复,但还是有两行以相同的订单号和客户名进入我的系统。哎呀!那就是我不使用钥匙而得到的!所以我使用实体框架删除一个。因为我知道重复项是今天发出的唯一订单,所以我这样做:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
你猜怎么了?我只是删除了重复的和原始的!那是因为我告诉实体框架,order_number / cutomer_name是我的主键。因此,当我告诉它删除duplicateOrder时,它在后台执行的操作类似于:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
有了那个警告……您现在应该一切顺利!