首页 > 解决方案 > 实体框架无法在实体构造函数中绑定值对象

问题描述

我创建了一个实体,它在其构造函数中将值对象作为参数,但是当我将实体添加到 db 上下文时,它会引发以下异常。

InvalidOperationException:找不到适合实体类型 >'BasketItem' 的构造函数。以下构造函数的参数无法>绑定到实体类型的属性:无法在>'BasketItem(Guid id,Guid productId,DateTimeOffset addedAt,Money price)'中绑定'price'。

我已经尝试builder.OwnsOne(x => x.Price);过类型配置。请记住,我正在使用内存存储提供程序。

篮子物品.cs

public sealed class BasketItem : Entity
{
    public Guid ProductId { get; private set; }
    public DateTimeOffset AddedAt { get; private set; }
    public Money Price { get; private set; }

    public BasketItem(Guid id, Guid productId, DateTimeOffset addedAt, Money price) : base(id)
    {
        ProductId = productId;
        AddedAt = addedAt;
        Price = price;
    }
}

钱.cs

public sealed class Money : ValueObject
{
    public decimal Value { get; private set; }
    public string CurrencyCode { get; private set; }

    public Money(decimal value, string currencyCode)
    {
        Value = value;
        CurrencyCode = currencyCode;
    }

    protected override IEnumerable<object> GetAtomicValues()
    {
        return new object[] { Value, CurrencyCode };
    }
}

标签: c#entity-framework-core

解决方案


使用 EF Core拥有的实体类型实现 DDD值对象有几个缺点,这是因为 EF Core 拥有的实体类型仍被视为实体,并且返回拥有的实体类型的属性被视为导航属性

在这种特殊情况下,问题是由上述最后一个事情以及以下实体类型构造函数限制引起的

需要注意的一些事项:

  • EF Core 无法使用构造函数设置导航属性(例如上面的博客或帖子)。

解决方法/解决方案是提供 EF 使用的特殊私有构造函数:

public BasketItem(Guid id, Guid productId, DateTimeOffset addedAt, Money price) : this(id, productId, addedAt)
{
    Price = price;
}

/// <summary>
/// EF constructor
/// </summary>
private BasketItem(Guid id, Guid productId, DateTimeOffset addedAt) : base(id)
{
    ProductId = productId;
    AddedAt = addedAt;
}

当然,使用[Owned]属性或OwnsOne流式 API 映射Money为拥有的实体类型。


推荐阅读