Преобразование классов в объекты с использованием 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.