FirstOrDefault returns 外键为空

FirstOrDefault returns null on foreign key

假设我们有以下模型:

public class ReadingOrder
{
    public virtual int Id { get; set; }
    public virtual Order Order { get; set; }
}

映射:

Table("db_ReadingOrder");
Id(o => o.Id).Column("Id").GeneratedBy.Identity();
References(o => o.Order, "OrderId");

我想得到 ReadingOrder,其中 orderId 等于 1(例如)。 但是当我尝试 FirstOrDefault 时,查询 returns null :

var readingO = _repositoryFactory.GetRepository<ReadingOrder>().FirstOrDefault(xz => xz.Order.Id == 1);

如果我得到所有这些并在应用后 FirstOrDefault 有效,但它很愚蠢:

var readingOrderList1 = _repositoryFactory.GetRepository<ReadingOrder>()
                         .GetAll().FirstOrDefault(xz => xz.Order.Id == 1);

存储库中的方法具有以下格式:

public T FirstOrDefault(Expression<Func<T, bool>> predicate)
{
   return _session.Query<T>().FirstOrDefault(predicate);
}

简单的东西,但行不通。如果我选择正常的 属性,比如 Id,一切都会按预期进行。 此外,如果我从日志中获取生成的查询并将其放入 sqlite,它会成功运行并返回读取顺序。 NHibernate 中有错误吗?是映射问题吗?还是 SQLite 的问题?

同样的场景在存储库中使用以下代码也能正常工作。

      public virtual IEnumerable<T> Get(
      Expression<Func<T, bool>> filter = null,
      Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
      string includeProperties = "")
    {

            IQueryable<T> query = _context.Set<T>();

            if (filter != null)
            {
                query = query.Where(filter);
            }
            if (includeProperties != null)
                foreach (var includeProperty in includeProperties.Split
                    (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    query = query.Include(includeProperty);
                }

            return query.ToList();
        }


    }

像这样修改您的class:

public class ReadingOrder
{
    public virtual int Id { get; set; }
    public virtual Order Order { get; set; }
    public virtual int OrderId { get; set; }    // Explicit and direct foreign Key
}

然后使用 OrderId 检索您的查询,而不是 Order.Id:

var readingO = _repositoryFactory.GetRepository<ReadingOrder>()
                                 .FirstOrDefault(xz => xz.OrderId == 1);

我认为有两种方法可以完成这项工作,或者将映射更改为:

Table("db_ReadingOrder");
Id(o => o.Id).Column("Id").GeneratedBy.Identity();
References(o => o.Order);

然后查询:

var readingO = _repositoryFactory.GetRepository<ReadingOrder>().FirstOrDefault(xz => xz.Order.Id == 1);

否则您也可以将映射更改为:

Table("db_ReadingOrder");
Id(o => o.Id).Column("Id").GeneratedBy.Identity();
References(o => o.Order).Column("OrderId");

然后查询:

var readingO = _repositoryFactory.GetRepository<ReadingOrder>().FirstOrDefault(xz => xz.Order.OrderId == 1);

好的,终于找到问题了:外键列的名称"OrderId"。 在这种情况下,Nhibernate 会查找 "Hibernate.Order",我不知道为什么,但是在我更改了列的名称之后,现在可以从 db 中检索该项目。谢谢大家的答案!我把赏金给了用户 Syed Farjad Zia Zaidi,因为他帮助我隔离了问题。很明显这是一个 Nhibernate 问题,所以再次感谢你。

有时这与动态全局过滤器有关,例如 IsDeleted prop 的软删除方法,因此您需要获取被忽略的项目并使用一些方法,例如 .IgnoreQueryFilters() in ef.