簡體   English   中英

無法使用AutoMapper與nhibernate解析子實體

[英]Unable to use AutoMapper to resolver child entities with nhibernate

我在嘗試解析模型中的子實體時遇到一系列問題,我在持久性上使用nhibernate,在ioc中使用windsor,在映射中使用automapper。

我已經通過多種方式對此進行了攻擊,並且在此過程中幾乎總是被封鎖,我們將不勝感激。

我對以下代碼的問題是,當我嘗試通過以下方法更新頁面布局時。 (假設只有layout-id在更改)

        var page = _pageRepository.Get(model.Id);
        Mapper.Map(model, page);

        using (ITransaction tran = _sessionFactory.BeginTransaction())
        {
            _pageRepository.Update(page);
            tran.Commit();
        }

我收到一個不錯的錯誤消息,

具有相同標識符值的另一個對象已與會話相關聯:用於布局模型。

現在,我嘗試了:-將工具更改為perwebrequest(然后說會話已關閉)-嘗試在獲取緩存后從緩存中刪除布局(上述錯誤)-我已經嘗試在解析器中獲取現有會話(上下文錯誤)

我應該如何進一步處理? 當然不能這么難! 我要去哪里錯了? 非常感謝。

這是所有重要的位。

我有一個這樣的模型:

public class ContentPage : Page
{ 
    public virtual Layout Layout { get; set; } 
}

我使用持久性工具來管理我的休眠會話,如下所示:

        Kernel.Register(
            Component.For<ISessionFactory>()
                .UsingFactoryMethod(_ => config.BuildSessionFactory()),

            Component.For<ISession>()
                .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
                .LifestylePerThread() <-- IMPORTANT FOR LATER.
            );

我的映射是這樣的:

        CreateMap<BlaViewModel, ContentPage>()
            .ForMember(dest => dest.DateModified, src => src.MapFrom(x => DateTime.UtcNow)) 
            .ForMember(x => x.Layout, x => x.ResolveUsing<EntityResolver<Layout>>().FromMember(y => y.Layout_Id));

最后我的解析器是這樣的:

public class EntityResolver<T> : ValueResolver<Guid, T> where T : EntityBase
{
    private readonly ISession _session;

    public EntityResolver(ISession session)
    {
        _session = session;
    }

    protected override T ResolveCore(Guid id)
    {
        var entity = _session.Get<T>(id); 
        return entity;
    }
}

唯一的例外是,您使用Session中存在的ID創建了一個新對象。 在您的情況下,AutoMapper可能會這樣做。

您如何在ContentPage地圖中配置Layout屬性? 如果默認情況下使用它,則AutoMapper將創建一個新的Layout對象並將ID設置為該對象,該對象不會從Session中加載。 然后保存該對象會導致異常。

因此,您需要自定義Layout屬性映射規則,如果它是現有模型,則從Session(存儲庫)中檢索它,並設置它的值(通過AutoMapper或手動),則會話狀態正確。

您為ContentPage配置的AutoMapper可能類似於:

Mapper.CreateMap<VPage, ContentPage>()
    ....
    .ForMember(des=>des.Layout, opt=>opt.MapFrom(src=>GetLayout(src))) //customize Layout
    ....;

在您的GetLayout函數中,它就像:

private Layout GetLayout(VPage page)
{
    var layout = page.LayoutId == 0? new Layout() : _layoutRepository.Get(page.LayoutId); //avoid new Layout object with existed Id
    .......

    return layout;
}

此外,最好不要使用AutoMapper從DTO轉換域模型,請參見以下說明

更新:很抱歉沒有看到您的EntityResolver,請嘗試使用LayoutRepository檢索它。

我的猜測是,解析器正在使用另一個會話來獲取布局。

// sample code
var layout1 = Resolve(1);

session.Attach(layout1);  // now contains layout 1

var layout2 = Resolve(1);

session.Attach(layout2);  // error: already contains layout with id 1


public Layout Resolve(int id)
{
    using (var session = OpenSession())
    {
        return GetNewSession.Get<Layout>(1);
    }
}

使用同一會話來解析連接的實體

幾個小時后,以典型的時尚形象出現了這一點,並學習了一些有關IOC的艱巨課程。

在上面的代碼中,您可以看到我注冊了我的ISession,如下所示

 Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(_ => config.BuildSessionFactory()),

        Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerThread() <-- IMPORTANT FOR LATER.
        );

這是我問題的開始,本質上是因為這是每個線程,幾乎所有不同點都將解決一個新Session。 以會話的多個實例結束。 (因此出現錯誤)

一旦將其更改為.LifestylePerWebRequest()事情會好一些,但仍然遇到一些Session麻煩。

最終弄清楚了通過Session的所有層(通過構造器進行IOC),因此我的Manager層,Repository層以及正在使用的所有地方都需要更改為PerWebRequest安裝。

喜歡:

container.Register(Classes.FromAssemblyContaining<Repository>()
                               .Where(Component.IsInSameNamespaceAs<Repository>())
                               .WithService
                               .DefaultInterfaces()
                               .LifestylePerWebRequest());

和:

        container.Register(Component.For<EntityResolver<Layout>>().ImplementedBy<EntityResolver<Layout>>().LifestylePerWebRequest());

正確使用我的IOC,最終達到了只處理一個會話(PerWebRequest)的地步,問題就消失了。

真好 希望對其他關注同一問題的人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM