简体   繁体   English

在Entity Framework 7中更新外键

[英]Updating foreign key in Entity Framework 7

I am trying to update a foreign key using Entity Framework 7. But it is giving error: The property 'Y' could not be found in object 'X'. 我正在尝试使用Entity Framework 7更新外键。但是它给出了错误:在对象“ X”中找不到属性“ Y”。 I have tried many different solution but still not working. 我尝试了许多不同的解决方案,但仍然无法正常工作。 The sample code: 示例代码:

class X
{
  property Y {get; set;} -> property Y is a foreign key and also a complex type
}

In table 'X' we have a column 'Y_ID' which is the foreign key. 在表“ X”中,我们有一列“ Y_ID”,即外键。

Note: I just want to update the foreign key. 注意:我只想更新外键。 Eg Initially class 'X' is pointing to 'NULL' , I want to update class 'X' to point to 'Y1' 例如, 最初,类“ X”指向“ NULL”我想更新类“ X”以指向“ Y1”

The Entity Framework 7 code: 实体框架7代码:

var x = this.GetX();
this.mainContext.Xs.Attach(x);
var xEntry = this.mainContext.Entry(x);

xEntry.Property("Y").CurrentValue = "Y1"; // Error at this line

await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

Detailed Error: 详细错误:

The property 'Y' on entity type 'X' could not be found. 找不到实体类型“ X”的属性“ Y”。 Ensure that the property exists and has been included in the model. 确保该属性存在并且已包含在模型中。

Edit 编辑

The approach Fabien suggested in his comment works fine. Fabien在评论中建议的方法效果很好。 But the problem is we only know about which property to update is at runtime. 但是问题在于我们只知道在运行时要更新哪个属性。 If I use reflection to achieve this, the problem is entity framework treats the object as new and tries to create it (INSERT) and then throws Primary Key violation (No duplicate entries allowed) 如果我使用反射来实现此目的,那么问题是实体框架将对象视为新对象并尝试创建它(插入),然后抛出主键冲突(不允许重复输入)

So, is there a way where I can't still update an object property which acts like a foreign key in EF? 因此,有没有办法我仍然无法更新像EF中的外键一样的对象属性? (I don't know exact property at compile time). (我不知道在编译时的确切属性)。

If you get the entities "X" and "Y" from your context, then they're automatically tracked by the ChangeTracker. 如果从上下文中获得实体“ X”和“ Y”,则ChangeTracker会自动跟踪它们。 So if you assign "Y" property of the "X" object with an "Y" instance retrieved from your context and call SaveChanges or SaveChangesAsync, EntityFramework will automically do the stuff for you. 因此,如果为“ X”对象的“ Y”属性分配了从上下文中检索的“ Y”实例并调用SaveChanges或SaveChangesAsync,则EntityFramework会自动为您完成这些工作。

var x = this.GetX();    
x.Y = "Y1";
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

By convention, your property "Y" on object "X" should be virtual to indicate that it's an foreign key. 按照惯例,对象“ X”上的属性“ Y”应为虚拟,以表明它是外键。


Edit 1 : 编辑1:

If I understand correctly, you want to update properties of your object dynamically at runtime, with values that comme from a web api. 如果我理解正确,则希望在运行时动态地更新对象的属性,并使用来自Web api的值。

1st way : 第一种方式:

Like you did, you can attach your "X" object to your context instance to begin tracking of the entity with EntityState.Unchanged, and then flag each property that need to be updated : 像您所做的一样,您可以将“ X”对象附加到上下文实例,以使用EntityState.Unchanged开始跟踪实体,然后标记每个需要更新的属性:

this.mainContext.Xs.Attach(x);
var entry = this.mainContext.entry(x);
entry.Property(p => p.Y).CurrentValue = "Y1";
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

When attaching an entity, you can specify the GraphBehavior, it tell EntityFramework if navigation properties should traversed or not. 附加实体时,可以指定GraphBehavior,它告诉EntityFramework是否应遍历导航属性。

2nd way : 第二种方式:

Using the DbSet.Update() method : 使用DbSet.Update()方法:

this.mainContext.Xs.Update(x);
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

It's automatically begin tracking of the entity with the state EntityState.Modified, all properties will be marked as modified. 它会自动开始跟踪状态为EntityState的实体。已修改,所有属性都将标记为已修改。 You should watch out when using this method, because all properties will be updated, if some of them are not inititialized in your "X" object, you could lost some data. 使用此方法时,请注意,因为所有属性都会更新,如果其中某些属性未在“ X”对象中初始化,则可能会丢失一些数据。 To prevent that case, you should always validate inputs. 为避免这种情况,您应始终验证输入。


If you want to keep your domain models de-coupled form any ORM, then you should think to separate entity types and domain types. 如果要使域模型与任何ORM分离,则应考虑将实体类型和域类型分开。 You can use an object mapper like Automapper to map entity to domain type and vice versa. 您可以使用对象映射器(例如Automapper)将实体映射到域类型,反之亦然。 In that way you clearly separate what you do at data access layer and business logic layer. 这样一来,您就可以清楚地区分在数据访问层和业务逻辑层的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM