我在遗留数据库上使用 Fluent nHibernate,并且有一个主 Person 表和几个包含有关此人的附加信息的扩展表。这些扩展表是一对一的,这意味着一个人在扩展表上只有一行,并且扩展表应该始终映射回一个人。
表:人员
列: PersonID、FirstName、LastName 等。
表: PersonLogin
列: PersonID(FK,唯一)、用户名、密码等。
我将我的映射定义为这样(省略了不相关的属性):
public PersonMap()
{
Table("Person");
Id(x => x.Id, "PersonID").Not.Nullable();
References(x => x.Login, "PersonID").LazyLoad();
}
public LoginMap()
{
Table("PersonLogin");
Id(x => x.Id, "PersonID").GeneratedBy.Foreign("Person");
References(x => x.Person, "PersonID").LazyLoad();
}
当我在两个表上都有数据时,这很有效,但我最近了解到一些扩展表没有所有 Person 行的数据。这导致我在查询期间遇到错误。所以,我添加.NotFound.Ignore()
到我的 PersonMap 使它看起来像这样:
References(x => x.Login, "PersonID").LazyLoad().NotFound.Ignore();
当我的业务层不需要投影任何扩展表值时,由于https://nhibernate.jira.com/browse/NH-1001 ,这导致我从登录表中获得不必要的选择。这导致我的一些搜索查询的性能很糟糕。
我搜索了很多帖子,但还没有找到关于如何解决这种情况的可靠答案。以下是我尝试过的选项:
选项一:
在扩展表上创建行以确保扩展表上没有没有行的人,然后删除.NotFound.Ignore()
.
这个选项的问题是它是一个遗留数据库,我不确定我需要在哪里更新以确保在插入 Person 时插入 PersonLogin。
选项二:
从我的 PersonMap 中删除 PersonLogin 引用,并在我的 Person 类中自定义加载它。像这样:
public class Person
{
/// <summary> Gets or sets the PersonID </summary>
public virtual int Id { get; set; }
private bool loadedLogin;
private PersonLogin login;
public virtual PersonLogin Login
{
get
{
if (!loadedLogin)
{
login = SessionManager.Session().Get<PersonLogin>(Id);
loadedLogin = true;
}
return login;
}
set
{
login = value;
loadedLogin = true;
}
}
}
我遇到的问题是,在执行查询以拉回大量 Person 对象及其登录时,我无法急切地获取数据。
选项三:
我刚开始玩,看看我是否可以编写一个自定义 IEntityNotFoundDelegate 来不为这些对象抛出异常。
private class CustomEntityNotFoundDelegate : IEntityNotFoundDelegate
{
public void HandleEntityNotFound(string entityName, object id)
{
if (entityName == "my.namespace.PersonLogin")
{
return;
}
else
{
throw new ObjectNotFoundException(id, entityName);
}
}
}
我将此添加到配置中
cfg.EntityNotFoundDelegate = new CustomEntityNotFoundDelegate();
它捕获了我的场景并立即返回而不是抛出错误,但是现在当我尝试将那些 PersonLogin 属性投影到我的业务对象上时,它正在尝试使用代理对象并抛出这个错误,我试图弄清楚我是否可以干净地处理(可能在 IPostLoadEventListener 中)。
System.Reflection.TargetException occurred
Message = Non-static method requires a target