【问题标题】:How to return nHibernate entity with nested entity having specific criteria如何返回具有特定条件的嵌套实体的 nHibernate 实体
【发布时间】:2014-08-25 03:57:28
【问题描述】:

我的 nHibernate 模型中有以下实体:

public class Customer : Entity {

    public Customer () {
        this.Notes = new List<Note>();
    }

    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }

    //....
    public virtual ICollection<Note> Notes { get; set; }
}

public class Note : Entity {

    public virtual Customer Customer { get; set; }
    public virtual DateTime Timestamp { get; set; }
    public virtual string Text { get; set; }
    public virtual NoteType NoteType { get; set; }
}

public class NoteType : Entity {

    public virtual string Description { get; set; }
    public virtual string ShortCode { get; set; } //ie. "X", "Y", "Z"

}

在我的控制器中,我想返回在过去 24 小时内有特定类型备注的客户列表。所以 ShortCode 有一个特定的值。我的控制器如下所示:

public class MyController : Controller {

    private IRepository<Customer> _repositoryCustomer;
    private IRepository<Note> _repositoryNote;

    public MyController (IRepository<Customer> repositoryCustomer, IRepository<Note> repositoryNote)
    {
            _repositoryCustomer = repositoryCustomer;
            _repositoryNote = repositoryNote;
    }

    public ActionResult Index()
    {
        var notes = _repositoryNote.GetAll().Where(n => n.Timestamp > DateTime.Now.AddDays(-1) && n.NoteType.ShortCode == "X");
        var customers = _repositoryCustomer.GetAll(); 
        //change above to only return customers with note from past 24 hours that has a short code of "X"

        //Not sure this is close to correct...
        //var customers = _repositoryCustomer.GetAll().Join(notes, c => c.Id, note => note.Customer.Id, (customer, note) => customer).ToArray();
        //but throws exception "Specified method is not supported." Seems to be failing in nHibernate

        return View(customers);
    }   
}

我需要做什么才能获得过去 24 小时内包含特定类型备注的客户列表?我的想法是使用 linq 或 IQueryable 方法,但我都在苦苦挣扎。谢谢!

【问题讨论】:

  • 是否可以假设在 _repositoryCustomer.GetAll() 方法中为客户填充了收款备注?

标签: c# linq nhibernate iqueryable


【解决方案1】:

正确答案是:

session.Query<Customer>()
       .Where(c => c.Notes.Any(n => n.Timestamp > DateTime.Now.AddDays(-1) &&
                                    n.NoteType.ShortCode == "X"))

(请根据您的情况将session.Query&lt;Customer&gt;() 替换为_repositoryCustomer.GetAll()

【讨论】:

  • 谢谢!我没有使用任何...完美!
【解决方案2】:

我通常会寻求这样的解决方案 -

  1. 首先在你的存储库中添加一个Get 方法来直接将表达式转换为nhibernate

    //can also sort to filter out best result
    public static IList<T> Get(Expression<Func<T, bool>> expression)
    {
        using (ISession session = OpenEngineSession())
        {
            return session.Query<T>().Where(expression).ToList();
        }
    }
    
  2. 然后这样称呼它 -

    var customers = _repositoryCustomer.Get(x => x.Notes.Any(n => n.Timestamp > DateTime.Now.AddDays(-1) && n.NoteType.ShortCode == "X"));
    

但您应该始终避免使用GetAll。比如这些——

var notes = _repositoryNote.GetAll().Where(n => n.Timestamp > DateTime.Now.AddDays(-1) && n.NoteType.ShortCode == "X");
var customers = _repositoryCustomer.GetAll(); 

原因是——

  1. GetAll()..... 将从数据库中获取实体到 Web 服务器的内存,然后在那里执行过滤。这是一个非常非常糟糕的主意,除非你有非常快的连接并且你有无限的 RAM。

  2. 将过滤器表达式直接发送到 NHibernate 可以让您灵活地利用数据库系统的全部潜力,并将网络传输保持在最低限度,更不用说只使用保存结果所需的内存。

【讨论】:

  • 感谢您的详细回复。我将不得不考虑创建自己的 Get 方法。我对 nHibernate 还很陌生。但是,当我使用 nHibernate 探查器检查 sql 时,我可以看到 Where/Any 组合在 Sql 中创建了 Where Exists 并且不会使用 GetAll() 方法恢复所有内容。所以我不得不接受 Hazzik 的回应。谢谢!
猜你喜欢
  • 2016-10-07
  • 1970-01-01
  • 2020-11-16
  • 2010-10-31
  • 2021-07-28
  • 1970-01-01
  • 2020-11-28
  • 2017-02-26
  • 2014-08-07
相关资源
最近更新 更多