我正在旧数据库上使用 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 从登录表中获得不必要的选择。它导致我的某些搜索查询的性能很差。

我搜索了很多帖子,但没有找到关于如何解决这种情况的可靠答案。以下是我尝试过的选项:

选项一:

在扩展表上创建行以确保扩展表上没有没有行的 Person ,然后删除 .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 属性投影到我的业务对象上时,它会尝试使用 Proxy 对象并抛出此错误,我想弄清楚我是否可以干净地处理(可能在 IPostLoadEventListener 中)。
System.Reflection.TargetException occurred
Message = Non-static method requires a target

最佳答案

我想我现在通过保留 .NotFound.Ignore() 来完成这项工作。

我原先声明:



我能够调整我的 LINQ 查询以在某些情况下使用 IQueryOver 并改进我在其他情况下对 LINQ 的使用以仅投影必要的值。这似乎已经解决了拉回扩展表的查询,因为投影中不需要它们的值。

我认为我的查询没有投影这些扩展表,但发现我有一个方法 ToKeyValuePair 我在投影中使用它来将 ID 和一些相关属性的 Name 字段连接在一起。该方法导致对象完全加载,因为 LINQ 无法在不加入扩展表的情况下确定所需字段是否存在。

关于nhibernate - 映射可能没有行的扩展表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15575378/

10-11 02:11