映射可能没有行的扩展表

时间:2013-03-22 16:30:57

标签: nhibernate fluent-nhibernate nhibernate-mapping

我在遗留数据库上使用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行的数据。这导致我在查询期间出错。所以,我在我的PersonMap中加了.NotFound.Ignore(),看起来像这样:

   References(x => x.Login, "PersonID").LazyLoad().NotFound.Ignore();

当我的业务层不需要投影任何扩展表值时,由于https://nhibernate.jira.com/browse/NH-1001而导致我从Login表中获得不必要的选择。它导致我的一些搜索查询中的性能很糟糕。

我搜索过很多帖子,但是没有找到关于如何解决这个问题的坚实答案。以下是我尝试过的选项:


选项一:

在扩展表上创建行,以确保扩展表上没有没有行的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

1 个答案:

答案 0 :(得分:2)

我认为我现在通过保留.NotFound.Ignore()来实现这一点。

我最初说过:

  

当我的业务层不需要投影任何扩展表值时,由于https://nhibernate.jira.com/browse/NH-1001而导致我从Login表中获得不必要的选择。它导致我的一些搜索查询中的性能很糟糕。

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

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