Entity framework 阻止EF尝试更新/插入子对象

Entity framework 阻止EF尝试更新/插入子对象,entity-framework,entity-framework-6,Entity Framework,Entity Framework 6,我有一个地址对象,它有一个城市属性。当创建一个全新的地址以通过EF6插入时,我会填写所有必需的基本地址属性(地址行1、邮政编码等),但我不需要完全水合的城市实例,只要它具有如下ID: address.City = new City { Id = 1 }; 当我尝试插入我的地址时,它也尝试对城市的属性进行验证,但我不想对城市进行任何CRUD,因为我只需要它的ID 我发现了下面的问题,它引导我从DbContext中分离条目,这样EF就不会试图对所述对象执行CRUD: 当我分离City实例时,似乎

我有一个地址对象,它有一个城市属性。当创建一个全新的地址以通过EF6插入时,我会填写所有必需的基本地址属性(地址行1、邮政编码等),但我不需要完全水合的城市实例,只要它具有如下ID:

address.City = new City { Id = 1 };
当我尝试插入我的地址时,它也尝试对城市的属性进行验证,但我不想对城市进行任何CRUD,因为我只需要它的ID

我发现了下面的问题,它引导我从
DbContext
中分离条目,这样EF就不会试图对所述对象执行CRUD:

当我分离City实例时,似乎会发生的事情是,它也会将其置空,因此我的地址具有null City属性。这是一个问题,因为City也是必需的,所以抛出一个
DbEntityValidationException
,表示“City字段是必需的”

我是EF的新手,所以也许我在这方面的做法一开始就错了

根据请求编辑,以下是我的全部代码:

在将我的地址实体传递到WebApi端点之前,在客户端中生成我的地址实体:

var user = new AppUser { Id = 1 };
var address = new Address
{
    City = new City { Id = 277 },
    Line1 = "123 whatever ln",
    PostalCode = "01233",
    CreatedBy = user,
    ModifiedBy = user,
    CreatedOn = DateTime.Today,
    ModifiedOn = DateTime.Today
};
在我的ASP.NET应用程序中,我创建了一个要与上下文分离的实例数组:

Detached = new object[] {
    value.Principle.ModifiedBy,
    value.Principle.CreatedBy,
    value.Principle.City
};
在保存之前,我分离阵列中的所有实例:

foreach (var d in DetachedObjects)
{
    dbContext.Entry(d).State = EntityState.Detached;
}
dbContext.SaveChanges();
我认为在分离属性时,它只是告诉EF不要对它们执行任何CRUD,但我不希望它将它们清空,因为我希望父/主实体具有其FK的ID

以下是我的地址和城市类别:

[DebuggerDisplay("{Line1}")]
public class Address : CisEntity
{
    [MaxLength(200)]
    [Required]
    public string Line1 { get; set; }

    [MaxLength(200)]
    public string Line2 { get; set; }

    [Required]
    public City City { get; set; }

    [MaxLength(25)]
    public string PostalCode { get; set; }
}

[DebuggerDisplay("{Name}, {Province.Name}, {Province.Country.Name}")]
public class City : CisEntity, IEntityName
{
    [Required]
    public Province Province { get; set; }

    [MaxLength(100)]
    public string Name { get; set; }
}

如果不希望在执行CRUD时需要城市,请删除必需的属性。如果您的程序中确实需要一个城市作为您的地址,但不需要数据库中的地址,那么在对地址执行CRUD之前,请按原样操作并清空城市部分。否则它将被插入。您应该检查一下数据库中的表是什么样子的。EF将在单独的表中跟踪这些数据,地址上的City列将是外键。如果在Address上使用必需属性装饰城市属性,则表示该列不可为空。这意味着在数据库中,此列必须包含城市表中记录的外键,因此城市必须存在。

我相信我理解您的问题,并且我将在3年后回答。哈哈

对于主要实体,
context.Addresses.Add(地址)

对于相关实体或子实体,
context.Entry(address.City).State=EntityState.Modified


对所有其他相关实体都这样做。

你能把你所有的
模型
上下文
相关的代码放在一起吗?我想你是做错了。如果需要城市,则必须有一个城市来插入地址,因为城市是必需的。如果你不觉得拥有一座城市是必要的,那么就不要要求它。至少,您应该发布您的实体,以便我们可以查看。@Gavin添加了代码。我知道如果需要城市,它应该有一个实例。问题是,分离城市实际上会使其无效,这不是我的意图。我只想保留City实例的ID,但我不想EF对其执行任何CRUD。在不插入它的情况下,如何生成
City
ID
?如果我的答案不能解决您的问题,请提供更多的代码,我们对您尝试执行的操作有更好的了解,我会相应地更新我的答案。我理解所有这些。我最终想要做的是为Address对象提供城市ID。我不需要完全水合的城市对象。然后我将尝试添加
public int CityId{get;set;}
,并使用必需的属性来寻址,并从城市属性中删除必需的属性。然后你就可以拥有你的Id,而不需要城市。我在一些EF代码示例中看到过这一点,但我不喜欢它(为什么要在EF应该足够聪明,知道它已经作为Id存在于城市对象上时添加CityId字段?)。似乎有一种方法可以说,“嘿,EF,需要一个City实例,但只确保它有一个键值,仅用于FK for Address”。EF足够聪明,知道City表中的某些列不可为null,这就是为什么它会给您这个问题。如果除Id外的所有列都可以为null,则不会出现此问题。仅供参考,我尝试分离City实例的原因是,如果我不这样做,EF会投诉City上的省属性为null,因为它也是必需的。我只是想避免在整个对象图中添加一条记录而使每个实例水合的兔子洞。在我的例子中,我不想插入子数据。意思是只插入父实体数据,并要求上下文忽略子实体。我已经一个接一个地尝试了这两条线路,但没有取得任何成功_dbContext.Entry(entity.City).State=Microsoft.EntityFrameworkCore.EntityState.Unchanged;或者_dbContext.Entry(entity.Shift).State=Microsoft.EntityFrameworkCore.EntityState.Detached;