При использовании Fluent Nhibernate AutoMap мои многие ко многим (с каскадом все) не вставляют / обновляют потомков - PullRequest
1 голос
/ 14 марта 2011

Вот мой сценарий (после прочтения первого проекта Fluent и автоматических страниц).У меня почти такая же настройка, за исключением того, что некоторые из моих соглашений отличаются от настроек по умолчанию, таких как имена таблиц и имена столбцов внешнего ключа.Я предоставил ручные переопределения для рассматриваемых отношений «многие ко многим»;одна сторона обратная, а другая нет.По некоторым причинам, это все еще не каскадное добавление.Я могу вручную добавить изображение в одиночку.Я также могу успешно прочитать всю схему вверх и вниз по иерархии.

Я попытался пропустить ручное переопределение сопоставления manyToMany;но в итоге я получаю прикольное имя таблицы ImageToPhotoSession в select, которое не удается.

Есть идеи?

Я должен отметить, что я использую: Nhibernate 3 Fluent 1.2 (бета)

Конфиг:

private readonly static ISessionFactory factory =
Fluently.Configure()
    .Database(MySQLConfiguration.Standard.ShowSql().ConnectionString(o => o.FromConnectionStringWithKey("Default")))
.Mappings(m =>
    m.AutoMappings.Add(AutoMap.AssemblyOf<Data.Image>(new TestMappingConfig())
        .Override<Data.PhotoSession>(map => map
            .HasManyToMany<Data.Image>(o => o.Images)
            .Cascade.All()
            .Table("photo_session_image"))
        .Override<Data.Image>(map => map
            .HasManyToMany(x => x.PhotoSessions)
            .Cascade.All()
            .Inverse()
            .Table("photo_session_image"))
        .Conventions.Add(
            Table.Is(x => Inflector.Net.Inflector.Underscore(x.EntityType.Name)),
            DefaultLazy.Always(),
            DefaultCascade.All(), 
            ForeignKey.EndsWith("Id")
 )))
.BuildSessionFactory();

Вот мои сущности данных:

public class Image
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual int SizeOnDisk { get; set; }
    public virtual string Hash { get; set; }
    public virtual int Width { get; set; }
    public virtual int Height { get; set; }
    public virtual string Description { get; set; }
    public virtual string Caption { get; set; }
    public virtual DateTime CreatedUtc { get; set; }
    public virtual DateTime ModifiedUtc { get; set; }
    public virtual DateTime ProcessedUtc { get; set; }
    public virtual string ContentType { get; set; }

    public virtual Site Site { get; set; }
    public virtual IList<PhotoSession> PhotoSessions { get; private set; }

    public Image()
    {
        this.PhotoSessions = new List<PhotoSession>();
    }
}

public class PhotoSession
{
    public virtual int Id { get; private set; }
    public virtual string Description { get; set; }
    public virtual DateTime CreatedUtc { get; set; }
    public virtual DateTime ModifiedUtc { get; set; }
    public virtual DateTime? EventDate { get; set; }

    public virtual IList<Image> Images { get; private set; }
    public virtual Site Site { get; set; }

    public PhotoSession()
    {
        Images = new List<Image>();
    }

    public virtual void AddImage(Image data)
    {
        data.PhotoSessions.Add(this);
        this.Images.Add(data);
    }
}

Вот фрагмент кода, который я пытаюсь использовать.

var repo = new Repository();
var site = repo.All<Data.Site>().Where(o => o.Id == 2).FirstOrDefault();
var img = new Data.Image()
{
    Name = "test",
    Caption = "test",
    ContentType = "image/jpeg",
    CreatedUtc = DateTime.UtcNow,
    Description = "test",
    Hash = "test",
    Height = 23,
    ModifiedUtc = DateTime.UtcNow,
    SizeOnDisk = 23,
    Width = 23
};

site.AddImage(img); 

//one to many, actually calls session.SaveOrUpdate(object) - fails to insert img
repo.Update(site); 

//gets a sample session
var session = repo.All<Data.PhotoSession>().Where(o => o.Id == 25).FirstOrDefault();

session.AddImage(img);

//many to many, actually calls session.SaveOrUpdate(object) - also fails to insert img and m2m row. 
repo.Update(session); 

И, наконец, вот журнал Sql, написанный Nhib.

NHibernate: select site0_.Id as Id3_, site0_.OwnerId as OwnerId3_, site0_.Layout
as Layout3_, site0_.Alias as Alias3_, site0_.CreatedUtc as CreatedUtc3_, site0_
.Domains as Domains3_, site0_.DefaultPageId as DefaultP7_3_, site0_.ResourceKey
as Resource8_3_ from site site0_ where site0_.Id=?p0 limit ?p1;?p0 = 2 [Type: In
t32 (0)], ?p1 = 1 [Type: Int32 (0)]

NHibernate: SELECT images0_.SiteId as SiteId1_, images0_.Id as Id1_, images0_.Id
 as Id0_0_, images0_.Name as Name0_0_, images0_.SizeOnDisk as SizeOnDisk0_0_, im
ages0_.Hash as Hash0_0_, images0_.Width as Width0_0_, images0_.Height as Height0
_0_, images0_.Description as Descript7_0_0_, images0_.Caption as Caption0_0_, im
ages0_.CreatedUtc as CreatedUtc0_0_, images0_.ModifiedUtc as Modifie10_0_0_, ima
ges0_.ProcessedUtc as Process11_0_0_, images0_.ContentType as Content12_0_0_, im
ages0_.SiteId as SiteId0_0_ FROM image images0_ WHERE images0_.SiteId=?p0;?p0 =
2 [Type: Int32 (0)]

NHibernate: select photosessi0_.Id as Id2_, photosessi0_.AccessCode as AccessCod
e2_, photosessi0_.Description as Descript3_2_, photosessi0_.CreatedUtc as Create
dUtc2_, photosessi0_.ModifiedUtc as Modified5_2_, photosessi0_.EventDate as Even
tDate2_, photosessi0_.SiteId as SiteId2_ from photo_session photosessi0_ where p
hotosessi0_.Id=?p0 limit ?p1;?p0 = 25 [Type: Int32 (0)], ?p1 = 1 [Type: Int32 (0
)]

NHibernate: SELECT images0_.PhotoSessionId as PhotoSes2_1_, images0_.ImageId as
ImageId1_, image1_.Id as Id0_0_, image1_.Name as Name0_0_, image1_.SizeOnDisk as
 SizeOnDisk0_0_, image1_.Hash as Hash0_0_, image1_.Width as Width0_0_, image1_.H
eight as Height0_0_, image1_.Description as Descript7_0_0_, image1_.Caption as C
aption0_0_, image1_.CreatedUtc as CreatedUtc0_0_, image1_.ModifiedUtc as Modifie
10_0_0_, image1_.ProcessedUtc as Process11_0_0_, image1_.ContentType as Content1
2_0_0_, image1_.SiteId as SiteId0_0_ FROM photo_session_image images0_ left oute
r join image image1_ on images0_.ImageId=image1_.Id WHERE images0_.PhotoSessionI
d=?p0;?p0 = 25 [Type: Int32 (0)]

1 Ответ

1 голос
/ 14 марта 2011

Оказывается, я не заключал свои операции в транзакцию сеанса.Глядя прямо на образец на веб-сайте Fluent NHibernates:

using (var session = sessionFactory.OpenSession())
{
    using (var transaction = session.BeginTransaction())
    {
     //... do stuff 
    }
}

В этом случае с учетом IoC класс Repository содержит внутреннюю ссылку на ISession и ITransaction.После завершения сеанса я установил новую транзакцию.Затем я создал Repository class IDisposable и после удаления я совершил транзакцию и закрыл сеанс.Я не должен ссылаться ни на что из Nhib за пределами Repository.

В итоге мой код выглядит так:

using (var repo = new Repository())
{
   ///do the same stuff in my third code sample from the question...
}
...