简体   繁体   English

实体框架核心:仅在没有额外调用的情况下更新与Id的关系

[英]Entity Framework Core: Update relation with Id only without extra call

I'm trying to figure out how to deal with 'Single navigation property case' described in this doc: 我正在试图弄清楚如何处理本文档中描述的“单一导航属性案例”

Let's say we have 2 models. 假设我们有2个型号。

class School
{
   public ICollection<Child> Childrens {get; set;}
   ...
}

and

class Child
{
    public int Id {get; set;}
    ...
}

So it's many-to-one relationship created by convention, without explicit foreign key in a Child . 因此,它是由约定创建的多对一关系,在Child没有显式外键。

So the question is if we have Child instance and know School.Id is there a way to update this relation without extra call to database to obtain School instance. 所以问题是我们是否有Child实例并且知道School.Id是否有一种更新此关系的方法,而无需额外调用数据库来获取School实例。

So the question is if we have Child instance and know School.Id is there a way to update this relation without extra call to database to obtain School instance. 所以问题是我们是否有Child实例并且知道School.Id是否有一种更新此关系的方法,而无需额外调用数据库来获取School实例。

Yes, it's possible. 是的,这是可能的。 You can create a fake stub School entity instance with Id only, Attach it to the DbContext (this way telling the EF that it is existing ), Attach the Child instance for the same reason, and then add the Child to the parent collection and call SaveChanges : 您可以创建一个假的存根 School与实体实例Id唯一, Attach它到DbContext (这样讲,它是现有的EF), AttachChild实例出于同样的原因,然后添加Child以父集合和呼叫SaveChanges

Child child = ...;
var schoolId = ...;

var school = new School { Id = schoolId };
context.Attach(school);
context.Attach(child);
school.Childrens.Add(child);
context.SaveChanges();

Update: Actually there is another cleaner way, since even if the entity has no navigation or FK property, EF Core allows you to access/modify the so called Shadow Properties 更新:实际上还有另一种清洁方式,因为即使实体没有导航或FK属性,EF Core也允许您访问/修改所谓的阴影属性

Shadow properties are properties that do not exist in your entity class. 阴影属性是实体类中不存在的属性。 The value and state of these properties is maintained purely in the Change Tracker. 这些属性的值和状态仅在Change Tracker中维护。

as soon as you know the name. 一旦你知道这个名字。 Which in your case, without configuration would be by convention "SchoolId" . 在您的情况下,没有配置将按照惯例"SchoolId"

So no fake School entity instance is needed, just make sure the Child is attached and then simply set the shadow property through ChangeTracker API: 因此,不需要伪School实体实例,只需确保附加了Child ,然后通过ChangeTracker API简单地设置shadow属性:

context.Attach(child);
context.Entry(child).Property("SchoolId").CurrentValue = schoolId;
context.SaveChanges();

Based on the updated question 根据更新的问题

No, there isn't ANY way you could do that by using ORM and strong typing that the ORM offers you, w/o 不,没有任何方法可以通过使用ORM和ORM为您提供的强类型来做到这一点,没有

  • Two-Way Navigation Property 双向导航属性
  • At least a ForeignKey/Principal property( SchoolId on Child ) 至少一个ForeignKey / Principal属性( SchoolId on Child
  • Having a shadow foreign key to the parent 拥有父外部的影子外键
  • performing a raw query (which beats the idea of having ORM for strong typing) and being DB agnostic at the same time 执行原始查询(这比使用ORM进行强类型操作的想法)和同时与DB无关

     // Bad!! Database specific dialect, no strong typing ctx.Database.ExecuteSqlCommandAsync("UPDATE Childs SET schoolId = {0}", schoolId); 

When you choose to use an ORM you have to accept certain technical limitations of the ORM framework in question. 当您选择使用ORM时,您必须接受相关ORM框架的某些技术限制。

If you want to follow Domain Driven Design (DDD) and remove all db specific fields form your entities, it won't be easy to use your domain models as entities. 如果要遵循域驱动设计(DDD)并从实体中删除所有特定于数据库的字段,则将域模型用作实体将非常简单。

DDD and ORM don't have very good synergies, there are way better approaches for this, but require a different architectural approach (namely: CQRS+ES (Command Query Responsibility Segregation with Event Sourcing). DDD和ORM没有很好的协同作用,有更好的方法,但需要不同的架构方法(即:CQRS + ES(命令查询责任分离与事件源)。

This works much better with DDD, since the Events from the EventSourcing are just simple (and immutable) message classes which can be stored as serialized JSON in the database and replayed to reconstruct the domain entity's state. 这对DDD来说效果要好得多,因为来自EventSourcing的事件只是简单(和不可变)的消息类,它们可以作为序列化的JSON存储在数据库中并重放以重建域实体的状态。 But that's a different story and one could write whole books about this topic. 但这是一个不同的故事,人们可以写关于这个主题的整本书。

Old Answer 老答案

The above scenario is only possible in a single DB operation, if your Child objects a navigation property/"back reference" to the parent. 如果您的Child将导航属性/“后向引用”对象表示父对象,则上述方案仅在单个数据库操作中可用。

class School
{
   public ICollection<Child> Childrens {get; set;}
   ...
}

and

class Child
{
    public int Id {get; set;}
    // this is required if you want do it in a single operation
    public int SchoolId { get; set; }
    // this one is optional
    public School { get; set; }
    ...
}

Then you can do something like: 然后你可以这样做:

ctx.Childs.Add(new Child { Id = 7352, SchoolId = 5,  ... });

Of course you first have to know the school Id and know it's valid, otherwise the operation will throw an exception if SchoolId is an invalid value, so I wouldn't recommend this approach. 当然,您首先必须知道学校ID并知道它是有效的,否则如果SchoolId是无效值,则操作将抛出异常,因此我不推荐这种方法。

If you only have the childId and not adding a whole new child you'll still have to get the child first. 如果你只有childId并且没有添加一个全新的孩子,你仍然必须childId孩子。

// childId = 7352
var child = ctx.Childs.FirstOrDefault(c => c.Id == childId);
// or use ctx.Childs.Find(childId); if there is a chance that 
// some other operation already loaded this child and it's tracked

// schoolId = 5 for example
child.SchoolId = schoolId;
ctx.SaveChanges();

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

相关问题 更新Entity Framework Core中的多对多关系 - Update a many-to-many relation in Entity Framework Core 实体框架-更新没有ID的实体 - Entity Framework - Update entities without Id 错误:“备用键属性‘id’为空”,“更新”调用 Cosmos DB 和 Entity Framework Core 3.1.2 - Error: "alternate key property 'id' is null" with "Update" call to Cosmos DB and Entity Framework Core 3.1.2 在实体框架核心中仅包含相关实体的Id - Including only Id of related entity in entity framework core 在实体框架核心 6 中进行多对多实体关系更新的正确方法是什么? - What is the correct way to do many to many entity relation update in Entity framework core 6? 使用迁移实体框架核心添加数据而无需指定ID - Add data using migration Entity Framework Core without specifying the id 如何在没有主键的情况下使用实体框架核心调用表 - How call tables without primary key with entity framework core 使用Entity Framework Core 1.0更新记录,而无需更新/更新范围 - Updating records with Entity Framework Core 1.0 without needing to Update/UpdateRange 如何仅更新实体框架(核心)中的特定字段 - How to only update specific fields in Entity Framework (Core) Entity Framework Core Put 请求仅部分更新不会更新文件 - Entity Framework Core Put request only partially updating will not update files
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM