От многих до многих отношений в NHibernate (Fluent NHibernate), создающих неожиданные записи в базе данных

78
7

Я использую Fluent NHibernate для многих и многих отношений между Магазином и Продуктом. Я не отправляю объекты, поскольку это не имеет значения. Это мои сопоставления


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentNHibernate.Mapping;
using FluentNHibernateSample.Domain;

namespace FluentNHibernateSample.Mappings
{
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Price);
HasManyToMany(x => x.Stores).Cascade.All().
Table("StoreProduct").ParentKeyColumn("ProductId")
.ChildKeyColumn("StoreId");
}
}
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentNHibernate.Mapping;
using FluentNHibernateSample.Domain;

namespace FluentNHibernateSample.Mappings
{
public class StoreMap : ClassMap<Store>
{
public StoreMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Staff).KeyColumn("StoreId").Cascade.All();
HasManyToMany(x => x.Products).Cascade.All().
Table("StoreProduct").
ParentKeyColumn("StoreId").ChildKeyColumn("ProductId");
}
}
}


Это мой пример кода, который пытается вставить записи в базу данных:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernateSample.Domain;

namespace FluentNHibernateSample
{
class Program
{
static void Main(string[] args)
{
ISessionFactory sessionFactory = CreateSessionFactory();

using (var session = sessionFactory.OpenSession())
{
session.Transaction.Begin();

Store store = new Store();
store.Name = "Emall";

Product product = new Product();
product.Name = "Emall Item 1";
product.Price = 12.5;

//Sample code below

session.Save(store);

session.Transaction.Commit();

Console.ReadKey();
}

}

private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure().
Database(MsSqlConfiguration.MsSql2008.
ConnectionString( m => m.FromConnectionStringWithKey(System.Environment.MachineName))).
Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>()).
BuildSessionFactory();
}
}
}


Пример кода:


            //option 1 ==> doesn't work
product.Stores.Add(store);

//option 2 ==> works
store.Products.Add(product);

//option 3 ==> creates 2 entries in Junction table
product.Stores.Add(store);
store.Products.Add(product);


Почему второй вариант работает, а 1-й - нет? Я понимаю, что это происходит, потому что я добавляю магазин в продукт и сохраняющий магазин. Но не должен ли первый вариант работать из-за отслеживания объектов? Дальше третий вариант меня полностью удивляет, создав 2 записи в таблице соединений. Как я могу решить эту проблему? Что-то не так в картировании классов?

спросил(а) 2021-01-19T18:53:51+03:00 6 месяцев назад
1
Решение
63

одна сторона двунаправленного многоточия должна быть той, которая отвечает за значение ассоциации, которое может вставлять записи привязки. Сторона, ответственная за отказ, должна сказать .Inverse(), чтобы сказать NH, что отвечает другая сторона.


// for example
HasManyToMany(x => x.Products).Inverse()

Обновление: чтобы быть последовательным, вам всегда нужно использовать option 3, иначе его подключить в db, но не inmemory, что приводит к тонким ошибкам


// in Store
public virtual void Add(Product product)
{
if(!Products.Contains(product))
{
Products.Add(product);
product.Add(this);
}
}

// in Product
public virtual void Add(Store store)
{
if(!Stores.Contains(store))
{
Stores.Add(store);
store.Add(this);
}
}

ответил(а) 2021-01-19T18:53:51+03:00 6 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема