我希望得到一些关于如何改进设计的反馈。具体来说,我不想为每个域对象创建一个新的存储库对象,但我也不想一遍又一遍地重写Session和Transaction逻辑。
为了减少编写代码以获取新会话和转换的需要,我创建的每个数据库事务和通用抽象类看起来像这样:
public class AbstractNHibernate<T> where T : class
{
public void Add<T>(T entity)
{
using(ISession session = NHibernateHelper.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(entity);
transaction.Commit();
}
}
}
这很棒,但后来我必须为每个域实体创建一个存储库,如下所示:
public class ConnectionModel : AbstractNHibernate<Connection>
{
public void SaveConnection(Connection conn)
{
Add(conn);
}
}
我可能有很多这些。有人可以提出不同的方法吗?
提前致谢。
答案 0 :(得分:2)
您的存储库(通常)不应该打开会话或执行事务。这应该在服务层或UI中完成。使用您当前的设计,无法让多个存储库参与同一事务。您可以通过在存储库构造函数中要求ISession来完成此任务。
我也不喜欢每个对象模型的一个存储库,更好的方法是将公共存储库函数逻辑地组合在一起。例如,CompanyRepository将具有处理公司和相关数据的方法 - CompanyType,CompanyStatus等。
答案 1 :(得分:0)
我看到这样做的方式(以及我如何做)是建立一个接口,创建一个实现这个接口的Nhiberate类(存储库模式)
使用规范模式也允许将查询传递到存储库。更多信息可以在这里找到:
http://www.mostlyclean.com/category/NHibernate.aspx
需要注意的是会话是在别处创建的,然后注入(传递)到存储库中,我使用像Windsor这样的IoC容器来执行此操作。
HTH
答案 2 :(得分:0)
也许我不理解你的问题?您似乎更多地询问如何实现泛型,因此您不必为每个对象创建特定于类型的类,而不是询问nhibernate问题。
这是一个接受任何类型T的简单存储库。您只需从类签名中删除T并实例化。但请记住,这只不过是一个会话包装器,更像是一个工作单元而不是一个存储库。实现查询将需要一些工作来尝试制作通用。您可以使用类似这样的东西作为您需要复杂查询的子类型的基类,如果您只支持对其他对象的非常基本的查询,也可以使用它作为独立实例。
/// <summary>
/// Repository defines simple class with standard methods
/// to accept and operate on any type.
/// </summary>
public class Repository
{
private ISession _session;
public ISession Session
{
get { return _session; }
}
/// <summary>
/// Save an entity.
/// </summary>
public void Save<T>(T entity)
{
Reconnect(_session);
try
{
_session.Save(entity);
}
finally
{
Disconnect(_session);
}
}
/// <summary>
/// Update an entity
/// </summary>
public void Update<T>(T entity)
{
Reconnect(_session);
try
{
_session.Update(entity);
}
finally
{
Disconnect(_session);
}
}
/// <summary>
/// Delete an entity
/// </summary>
public void Delete<T>(T entity)
{
Reconnect(_session);
try
{
_session.Delete(entity);
}
finally
{
Disconnect(_session);
}
}
/// <summary>
/// Retrieve an entity
/// </summary>
public T GetById<T>(Guid id)
{
Reconnect(_session);
try
{
return _session.Get<T>(id);
}
finally
{
Disconnect(_session);
}
}
/// <summary>
/// Method for flushing the session.
/// </summary>
public void Flush()
{
Reconnect(_session);
try
{
_session.Flush();
_session.Clear();
}
finally
{
Disconnect(_session);
}
}
/// <summary>
/// Reconnect to the session. Accept parameter so we can use anywhere.
/// </summary>
public void Reconnect(ISession session)
{
if (!session.IsConnected)
{
session.Reconnect();
}
}
/// <summary>
/// Disconnect from the session. Accept parameter so we can use anywhere.
/// </summary>
public void Disconnect(ISession session)
{
if (session.IsConnected)
{
session.Disconnect();
}
}
public Repository(ISession session)
{
_session = session;
}
}
}