Преобразование классов в объекты с использованием Domain Driven Design с NHibernate в качестве ORM

Здравствуйте, я хочу сопоставить класс с инкапсулированными полями. Раньше я использовал EF Core для сопоставления моделей предметной области с сущностями, но на этот раз я хочу попробовать что-то новое и выбрал NHibernate в качестве ORM. Ниже приведены мои классы домена:

      public class Order
{
    public virtual EntityId Id { get; }
    public virtual OrderNumber OrderNumber { get; private set; }
    public virtual DateTime Created { get; }
    public virtual string Note { get; private set; } = null;

    public virtual IEnumerable<ProductSale> Products => _products;
    private IList<ProductSale> _products = new List<ProductSale>();

    protected Order() { }

    public Order(EntityId id, OrderNumber orderNumber, DateTime created, string note = null, IEnumerable<ProductSale> products = null)
    {
        Id = id;
        ChangeOrderNumber(orderNumber);
        Created = created;

        if (products != null)
        {
            AddProducts(products);
        }

        Note = note;
    }

    public virtual void ChangeOrderNumber(string orderNumber)
    {
        OrderNumber = orderNumber;
    }

    public virtual void ChangeNote(string note)
    {
        Note = note;
    }

    public virtual void AddProducts(IEnumerable<ProductSale> products)
    {
        // some logic and operations
    }

    public virtual void AddProduct(ProductSale product)
    {
        // some logic and operations
    }

    public virtual void RemoveProduct(ProductSale product)
    {
        // some logic and operations
    }
}

public sealed class ProductSale
{
    public virtual EntityId Id { get; }
    public virtual Order Order { get; private set; } = null;
    public virtual ProductSaleState ProductSaleState { get; private set; } = ProductSaleState.New; // enum

    protected ProductSale() { }

    public ProductSale(EntityId id, ProductSaleState productSaleState, Order order)
    {
        Id = id;
        Order = order;
        ProductSaleState = productSaleState;
    }

    public virtual void AddOrder(Order order)
    {
        // logic
    }

    public virtual void RemoveOrder()
    {
        // logic
    }
}

Мои объекты значения:

      public class EntityId : IEquatable<EntityId>
{
    public virtual Guid Value { get; protected set; }

    protected EntityId() { }

    public EntityId(Guid value)
    {
        // validation

        Value = value;
    }

    public static EntityId Create() => new(Guid.NewGuid());

    public override bool Equals(object obj)
    {
        return Equals(obj as EntityId);
    }

    public bool Equals(EntityId other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Value == other.Value;
    }

    public override int GetHashCode()
    {
        return GetEqualityComponents()
                .Select(x => x != null ? x.GetHashCode() : 0)
                .Aggregate((x, y) => x ^ y);
    }

    private IEnumerable<object> GetEqualityComponents()
    {
        yield return Value;
    }
}

public sealed class OrderNumber : IEquatable<OrderNumber>
{
    public virtual string Value { get; protected set; }

    public OrderNumber(string productName)
    {
        ValidProductName(productName);
        Value = productName;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as OrderNumber);
    }

    public bool Equals(OrderNumber other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Value == other.Value;
    }

    public override int GetHashCode()
    {
        return GetEqualityComponents()
                .Select(x => x != null ? x.GetHashCode() : 0)
                .Aggregate((x, y) => x ^ y);
    }

    private IEnumerable<object> GetEqualityComponents()
    {
        yield return Value;
    }

    private static void ValidProductName(string productName)
    {
        // validation
    }
}

Мои сопоставления:

      public sealed class OrderConfiguration : ClassMapping<Order>
{
    public OrderConfiguration ()
    {
        Table("Orders");
        ComponentAsId(a => a.Id, map =>
        {
            map.Access(Accessor.ReadOnly);
            map.Property(id => id.Value, prop =>
            {
                prop.Access(Accessor.ReadOnly);
                prop.Column(nameof(Order.Id));
            });
        });
        Component(a => a.OrderNumber, map =>
        {
            map.Property(ad => ad.Value, prop => 
            {
                prop.Access(Accessor.ReadOnly);
                prop.Column(nameof(Order.OrderNumber));
            });
        });
        Property(a => a.Created, prop=> {
            prop.Access(Accessor.ReadOnly);
            prop.Column(nameof(Order.Created));
        });
        Property(a => a.Note, map => map.Column(nameof(Order.Note)));
        Bag(o => o.ProductSales, map =>
        {
            map.Table("ProductSales");
            map.Key(k => k.Column(col => col.Name("OrderId")));
        }, map => map.OneToMany());
    }
}

public class ProductSaleConfiguration : ClassMapping<ProductSale>
{
    public ProductSaleConfiguration()
    {
        Table("ProductSales");
        ComponentAsId(a => a.Id, map =>
        {
            map.Access(Accessor.ReadOnly);
            map.Property(id => id.Value, prop =>
            {
                prop.Access(Accessor.ReadOnly);
                prop.Column(nameof(ProductSale.Id));
            });
        });
        Property(p => p.ProductSaleState, map => {
            map.Column(nameof(ProductSale.ProductSaleState));
            map.Type<EnumStringType<ProductSaleState>>();
        });
        ManyToOne(p => p.Order, map =>
        {
            map.Column("OrderId");
        });
    }
}

Когда я вставлял объект, например заказ, EntityId всегда был установлен как нуль. Я до сих пор не использовал NHibernate в качестве ORM, поэтому я не мог проверить правильность сопоставлений. Может быть, чего-то не хватает. Я использовал .Net 6, базу данных SQLite.

0 ответов

Другие вопросы по тегам