Хорошо, это будет стена текста, но .... в основном, у меня есть следующие 3 класса:
public class Address
{
public virtual int Id { get; private set; }
public virtual string Street { get; set; }
public virtual string POBox { get; set; }
public virtual string ZIP { get; set; }
public virtual string Locality { get; set; }
public virtual Country Country { get; set; }
public virtual ICollection<Customer> CustomersLivingHere { get; set; }
}
public class Customer
{
public virtual int Id { get; private set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
public virtual DateTime Birthdate { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class Country
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual string Domain { get; set; }
}
Это какая-то адресная книга (очевидно, она немного сложнее в реальном мире, но я уже сократил свои модульные тесты до этого нерабочего случая).
Адреса проверяются и нормализуются с помощью веб-службы, предоставляемой третьей стороной, поэтому в идеале я хотел бы, чтобы отношения между клиентами и адресами были многим-множественными, чтобы каждый адрес в базе данных нуждался в пройти валидацию только один раз (мы платим деньги за услугу валидации), оставаясь при этом связанным с любым количеством клиентов.
В то же время я бы хотел, чтобы NHibernate автоматически сохранял адреса, как только я назначил их объекту клиента, и сохранил их, но пока это не работает вообще.
Вот так выглядят мои файлы сопоставления для класса Customer:
public class CustomerMap : FluentNHibernate.Mapping.ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.Id);
Map(x => x.Firstname).Length(256);
Map(x => x.Lastname).Length(256);
Map(x => x.Birthdate);
HasMany(x => x.Addresses)
.AsSet()
.Inverse()
.Cascade.All();
}
}
... и это отображение адресов:
public class AddressMap : FluentNHibernate.Mapping.ClassMap<Address>
{
public AddressMap()
{
Id(x => x.Id);
Map(x => x.Street);
Map(x => x.POBox);
Map(x => x.ZIP).Length(16).Not.Nullable();
Map(x => x.Locality).Length(128).Not.Nullable();
References(x => x.Country).Not.Nullable();
HasManyToMany(x => x.CustomersLivingHere)
.Table("CustomerAddress");
}
}
То, что я ожидаю сделать, - это просто что-то вроде:
Страна someCountry = Новая Страна
{
Код = "CL",
DialPrefix = "+56",
Имя = "Чили",
Домен = ".cl"
}; * 1 018 *
1020 *
Address[] Addresses = new[] {
new Address
{
Country = someCountry,
Locality = "Providencia",
Street = "Pasaje Anakena 123",
ZIP = "7510115"
},
new Address
{
Country = someCountry,
Locality = "Providencia",
Street = "Perez Valenzuela 1520",
ZIP = "7500035"
}
};
Customer[] Customers = new[] {
new Customer
{
Addresses = new[] {Addresses[0], Addresses[1]},
Firstname = "Jane",
Lastname = "Doe"
}
* *} 1 022;
1025 *
using (ISession session = _sessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
foreach (Customer customer in Customers)
{
session.Save(customer);
}
transaction.Commit();
}
}
Выполнение модульного теста, содержащего код, подобный этому, в основном приводит к NHibernate.StaleStateException: Неожиданное количество строк: 0; ожидается: 1
Я прочитал около 35 записей в блоге и ТАК вопросы, но в основном они касались назначенных идентификаторов, которые я не использую - я посмотрел на файлы сопоставления, сгенерированные Fluent Hibernate, и класс генератора всегда «идентичность».
Я посмотрел на выходные данные SQL и журналы отладки NHibernate, и кажется, что NHibernate каким-то образом назначил идентификаторы некоторым объектам вместо значения по умолчанию, что приводит к тому, что NHibernate пытается выдавать UPDATE вместо операторов SELECT - я понятия не имею почему же.
Любое понимание того, как это исправить, или даже общие советы по правильному моделированию такого рода отношений, несомненно, будет оценено.