C# EF Core中的Owned types集合从未更新

C# EF Core中的Owned types集合从未更新,c#,entity-framework-core,owned-types,C#,Entity Framework Core,Owned Types,我有一个如下定义的聚合: public class Product { public int LocalId { get; private set; } public Something Something { get; private set; } public ICollection<Price> Prices { get; private set; } } public class Something { public string Name

我有一个如下定义的聚合:

public class Product {
    public int LocalId { get; private set; }
    public Something Something { get; private set; }
    public ICollection<Price> Prices { get; private set; }
}

public class Something {
    public string Name { get; set; }
}

public class Price {
    public int Type { get; set; }
    public decimal Value { get; set; }
}
private void DefineProduct(ModelBuilder builder) =>
    builder
        .Entity<Product>(builder =>
        {
            builder.HasKey(p => p.LocalId);
            builder
                .OwnsOne(p => p.Something, smth =>
                {
                    smth.ToTable("somethings");
                })
                .OwnsMany(p => p.Prices, pp =>
                {
                    pp.ToTable("prices");
                });
        });
public async Task UpdateProperties(Product product, IEnumerable<object> props)
{
    _context.Attach(product);
    _context.Update(product);

    foreach (var prop in props)
    {
        _context.Update(prop);
    }

    try
    {
        await _context.SaveChangesAsync();
    } 
    catch (Exception ex)
    {
        Console.WriteLine("Who the hell allowed such a bug to go into a production release?");
    }
}
然后我试着像这样保存产品:

public class Product {
    public int LocalId { get; private set; }
    public Something Something { get; private set; }
    public ICollection<Price> Prices { get; private set; }
}

public class Something {
    public string Name { get; set; }
}

public class Price {
    public int Type { get; set; }
    public decimal Value { get; set; }
}
private void DefineProduct(ModelBuilder builder) =>
    builder
        .Entity<Product>(builder =>
        {
            builder.HasKey(p => p.LocalId);
            builder
                .OwnsOne(p => p.Something, smth =>
                {
                    smth.ToTable("somethings");
                })
                .OwnsMany(p => p.Prices, pp =>
                {
                    pp.ToTable("prices");
                });
        });
public async Task UpdateProperties(Product product, IEnumerable<object> props)
{
    _context.Attach(product);
    _context.Update(product);

    foreach (var prop in props)
    {
        _context.Update(prop);
    }

    try
    {
        await _context.SaveChangesAsync();
    } 
    catch (Exception ex)
    {
        Console.WriteLine("Who the hell allowed such a bug to go into a production release?");
    }
}
公共异步任务更新属性(产品、IEnumerable props)
{
_上下文。附加(产品);
_更新(产品);
foreach(道具中的var道具)
{
_上下文更新(prop);
}
尝试
{
wait_context.SaveChangesAsync();
} 
捕获(例外情况除外)
{
WriteLine(“到底是谁允许这样一个bug进入生产版本的?”);
}
}
现在我应该提到,该产品来自一个初始查询,其结果没有被跟踪(通过
AsNoTracking()
call),这就是为什么我要调用方法体第一行中的
Attach
方法。问题是,我在点击
catch
语句时,出现了一条异常消息,内容是:

数据库操作预期影响1行,但实际影响0行 世界其他地区。自实体被删除后,数据可能已被修改或删除 加载。寻找 关于理解和处理乐观并发的信息 例外情况。”}


问题是,我没有在其他任何地方更新同一个产品,这是唯一接触它的地方。此外,我使用
AsNoTracking
作为默认值。如果我用
\u context.Update(prop)注释掉行5944关于EF Core,我想我也理解这种行为的原因,但我不确定。当我在
Price
对象上添加Id字段时,我的代码开始正常运行。我的怀疑是,如果没有显式可见的Id属性,任何附加或更新都不会使EF看到和该对象。我欢迎文档关于它的说明部分…

EF核心文档明确指出,您必须定义拥有的实体PK(与影子FK通常用作PK的
OwnsOne
相反)

因此,您需要定义它自己的PK(比如
Id
),或者定义复合PK-例如,如果
Price.Type
在所有者内部是唯一的,那么您可以使用

pp.HasKey("LocalId", "Type");

并避免额外的
Id
列。

您好,不完全确定:
\u context.Attach(product.State=EntityState.Modified;
向EF发出信号,指示它应该重新跟踪它。(对于EF非核心:
\u context.Entry(product.State=EntityState.Modified;
)我收到了相同的错误:(虽然我无法很快找到说明当您不提供密钥时会发生什么的文档,但这里有一些文档。按照惯例,您在添加Price.Id时添加了一个密钥。问题是,主键是由数据库中的EF框架创建的。它与您提供的链接中的一句相反,该链接说类型需要一个主键。既然它是自动创建的,为什么我需要在架构定义中显式地提到它呢?它应该是显式的,除非有异常向我喊叫,在没有显式地命名主键的情况下我不能定义一个拥有的集合类型,或者是100%隐式的,所以自动创建的主键就足够了。现在它是这只是让人困惑……同时获取DbUpdateConcurrencyException类型的异常也无助于调试问题:(您写道:“当我在Price对象上添加Id字段时,我的代码开始正常运行"。所以在此之前它不是自动为您创建的。无论如何,该链接是官方的EF核心文档,因此如果它是最新的,那么它应该是它所说的内容。顺便说一句,您还没有指定EF核心版本,这也可能很重要,因为它们在即使是较小的版本之间更改/中断了许多内容。例外情况如何,它们使用基本版本对于每一个可能的错误,例如试图删除或更新不存在的记录。因此,是的,消息是误导性的:-(好的,然后我错过了一个重要的信息位-db表有一个主键列,名为id,由orm创建。无论如何,感谢您的解释!