是否可以将 NHibernate 持久实体放入会话的同一生命周期范围内?

发布于 2024-11-19 20:51:10 字数 988 浏览 1 评论 0 原文

我想将持久实体放入 NHibernate 会话的相同生命周期范围中,这可能吗?

public class ViewModel
{
    readonly Func<Owned<ISession>> _sessionFactory;

    public ViewModel(Func<Owned<ISession>> sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    public void DoSomething()
    {
        using (var session = _sessionFactory())
        {
            using (var trans = session.Value.BeginTransaction())
            {
                session.Value.Get<Model>(1).DoSomething();
                trans.Commit();
            }
        }
    }
}

public class Model
{
    readonly ILifetimeScope _lifetimeScope;

    public Model(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
    }

    public void DoSomething()
    {
        ISession session = _lifetimeScope.Resolve<ISession>();
        Model model = session.Get<Model>(2);
        model.Text = "test";
    }

    public string Text { get; set; }
}

I want to put the persistent entities to the same lifetimescope of the NHibernate session, is it possible?

public class ViewModel
{
    readonly Func<Owned<ISession>> _sessionFactory;

    public ViewModel(Func<Owned<ISession>> sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    public void DoSomething()
    {
        using (var session = _sessionFactory())
        {
            using (var trans = session.Value.BeginTransaction())
            {
                session.Value.Get<Model>(1).DoSomething();
                trans.Commit();
            }
        }
    }
}

public class Model
{
    readonly ILifetimeScope _lifetimeScope;

    public Model(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
    }

    public void DoSomething()
    {
        ISession session = _lifetimeScope.Resolve<ISession>();
        Model model = session.Get<Model>(2);
        model.Text = "test";
    }

    public string Text { get; set; }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

超可爱的懒熊 2024-11-26 20:51:10

将构造函数注入 NHibernate 实体的方法是使用 IInterceptor。来自 http://www.nhforge.org/doc/nh/en/ #objectstate-拦截器

拦截器有两种类型:ISession 范围和 ISessionFactory 范围。

当使用接受 IInterceptor 的重载 ISessionFactory.OpenSession() 方法之一打开会话时,指定 ISession 范围的拦截器。

ISession session = sf.OpenSession( new AuditInterceptor() );

看起来您已经设置了容器来解析 ISession。您只需更改它,以便它具有可以实例化您的实体的作用域拦截器。我想象这样的事情:

public class AutofacInterceptor : NHibernate.EmptyInterceptor
{
    Autofac.ILifetimeScope scope;

    public AutofacInterceptor(Autofac.ILifetimeScope scope)
    {
        this.scope = scope;
    }

    public override object Instantiate(string entityName, EntityMode entityMode, object id)
    {
        // use the LifetimeScope to instantiate the correct entity
    }
}

并告诉 Autofac 用你的拦截器解析 ISessions,也许像这样:

builder.Register(c =>
{
    var scope = c.Resolve<ILifetimeScope>();
    var factory = c.Resolve<NHibernate.ISessionFactory>();
    return factory.OpenSession(new AutofacInterceptor(scope));
})
.As<NHibernate.ISession>();

这是未经测试的,但我认为这是正确的轨道。您可能需要或想要定义自己的会话工厂,而不是使用 Func>

旁注:您的示例显示您从实体访问 ISession 。我认为这很不寻常。有些人,喜欢 Udi,不喜欢将任何东西注入实体;其他人说你需要注入服务以避免领域模型贫乏。但我从未见过将会话注入实体。

The way to do constructor injection into NHibernate entities is to use an IInterceptor. From http://www.nhforge.org/doc/nh/en/#objectstate-interceptors

Interceptors come in two flavors: ISession-scoped and ISessionFactory-scoped.

An ISession-scoped interceptor is specified when a session is opened using one of the overloaded ISessionFactory.OpenSession() methods accepting an IInterceptor.

ISession session = sf.OpenSession( new AuditInterceptor() );

It looks like you already have the container set up to resolve ISessions. You just need to change it so that it has a scoped interceptor that can instantiate your entities. I'd imagine something like this:

public class AutofacInterceptor : NHibernate.EmptyInterceptor
{
    Autofac.ILifetimeScope scope;

    public AutofacInterceptor(Autofac.ILifetimeScope scope)
    {
        this.scope = scope;
    }

    public override object Instantiate(string entityName, EntityMode entityMode, object id)
    {
        // use the LifetimeScope to instantiate the correct entity
    }
}

And tell Autofac to resolve ISessions with your interceptor, maybe like this:

builder.Register(c =>
{
    var scope = c.Resolve<ILifetimeScope>();
    var factory = c.Resolve<NHibernate.ISessionFactory>();
    return factory.OpenSession(new AutofacInterceptor(scope));
})
.As<NHibernate.ISession>();

This is untested, but I think it's the right track. You may need or want to define your own session factory rather than using Func<Owned<ISession>>.

A side note: your example shows you accessing the ISession from your entity. I think this is unusual. Some people, like Udi, don't like to inject anything into entities; others say you need to inject services to avoid an anemic domain model. But I've never seen injecting the session into entities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文