保存相关记录而不创建重复的主体记录 [英] Saving dependent record without creating a duplicate principal record

查看:89
本文介绍了保存相关记录而不创建重复的主体记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用EF Core,我正在创建主体记录,但是在添加和保存从属记录时,它将尝试创建新的重复主体。

With EF Core I am creating a principal record, but when adding and saving a dependent record it will attempt to create a new duplicate principal.

我见过各种解决方案,但我想知道为什么要这样做才能解决问题。

I've seen various solutions to this, but I'd like to know why this is happening to make a proper fix.

实体模型采用这种方式。

The entity models are in this fashion.

public class Company
{
    public string ID { get; set; }
    public string Name { get; set; }
}

public class Employee
{
    public string ID { get; set; }
    public string Title { get; set; }
    public string Name { get; set; }

    public string CompanyID { get; set; }

    [ForeignKey("CompanyID")]
    public Company Company { get; set; }
}

A DbContext 创建为将这些内容公开为 DbSet

A DbContext is created to expose with of these as a DbSet.

public class OrganizationContext : DbContext
{
    public DbSet<Company> Companies { get; set; }
    public DbSet<Employee> Employees { get; set; }

    // ...
}

通过时在视图中通过 OrganizationContext 将雇员添加到公司的完整对象中,它还将尝试创建新的公司记录。

When passing in a full object from a View to add an Employee to a Company via OrganizationContext, it will attempt to create a new Company record as well.

var comp = new Company()
{
    comp.ID = "1",
    comp.Name = "The Daily Planet"
};

var emp = new Employee()
{
    emp.ID = "00123",
    emp.Title = "Supervisor",
    emp.Name = "Clark Kent",
    emp.CompanyID = "1",
    emp.Company = comp
};

_context.Employees.Add(emp);
_context.SaveChanges();

如果我将Company属性设置为不变,它仍会尝试插入新公司。

If I set the Company attribute to be unchanged, it still attempts to insert a new Company.

_context.Employees.Add(emp);
_context.Entry(emp.Company).State = EntityState.Unchanged;
_context.SaveChanges();

如果我将 emp.Company 设置为 null ,它将不会尝试添加新公司

If I set emp.Company to null, it won't attempt to add a new Company

emp.Company = null;
_context.Employees.Add(emp);

是否存在正确的方法来建立模型关系或添加结构

Is there a correct way to setup model relationships or a structure to add an Employee to a Company without needing to manually alter the object graph before saving?

推荐答案

这是因为您正在使用 Add 方法,该方法通过定义 Add 操作级联到每个可访问实体:

It's because you are using Add method, which by definition cascades the Add operation to each reachable entity:


如果创建几个新的相关实体,将其中一个添加到上下文中也会导致其他实体也被添加。

If you create several new related entities, adding one of them to the context will cause the others to be added too.

如果您使用的是带有自动生成的PK的实体,则正确的方法是使用 Update 方法,如新旧e的混合现有实体

If you were using entities with auto generated PKs, the correct way would be to use Update method as explained in the Mix of new and existing entities:


使用自动生成的键,即使图形也可以用于更新和插入包含需要插入的实体和需要更新的实体的组合

With auto-generated keys, Update can again be used for both inserts and updates, even if the graph contains a mix of entities that require inserting and those that require updating

后跟一个示例,然后:


如果没有设置键值,更新将标记图形,博客或帖子中的任何实体以供插入,而将所有其他实体标记为更新。 / p>

Update will mark any entity in the graph, blog or post, for insertion if it does not have a key value set, while all other entities are marked for update.

不幸的是,您的情况有所不同。没有通用的现成方法可以执行添加或更新。一种解决方案是不设置导航属性,而仅设置FK属性(幸运的是):

Unfortunately your case is different. There is no universal out of the box method for performing the add or update. One solution is to not set the navigation property, but only the FK property (which you luckily have):

//var comp = new Company()
//{
//    comp.ID = "1",
//    comp.Name = "The Daily Planet"
//};

var emp = new Employee()
{
    emp.ID = "00123",
    emp.Title = "Supervisor",
    emp.Name = "Clark Kent",
    emp.CompanyID = "1",
    //emp.Company = comp
};

_context.Employees.Add(emp);
_context.SaveChanges();

另一种会导致数据库往返的费用是从上下文中解决相关的现有实体: / p>

Another way which will cost you a db roundtrip is to resolve the related existing entity from the context:

var comp = _context.Companies.Find("1");

var emp = new Employee()
{
    emp.ID = "00123",
    emp.Title = "Supervisor",
    emp.Name = "Clark Kent",
    //emp.CompanyID = "1", // Not needed, but won't hurt if you include it
    emp.Company = comp
};

_context.Employees.Add(emp);
_context.SaveChanges();

最后一个选择是使用 TrackGraph 并为每个实体分别决定。

The last option is to use TrackGraph and decide individually for each entity.

这篇关于保存相关记录而不创建重复的主体记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆