【问题标题】:How to architect my service/repository code with Linq2Sql!如何使用 Linq2Sql 构建我的服务/存储库代码!
【发布时间】:2010-02-23 08:48:31
【问题描述】:

我在构建应用程序时遇到问题。

我有以下结构,只显示了重要方面。

namespace Domain
{
   public class Invoice
   {
     //properties
   }

public class InvoiceRepository
{
   public Linq2SqlContext context = new Linq2SqlContext();

   public IQueryable<Invoice> GetInvoices()
   {
              var query = from inv in _dbctx.Invoices orderby inv.invInvoiceDate descending select GetInvoice(inv) ;

            return query;

   }
}
public class InvoiceService()
{
   public InvoiceRepository _repository = new InvoiceRepositroy();
   public IQueryable<Invoice> GetInvoices()
   {
      return _repository.GetInvoices();
   }   

}
}

namespace MyApp
{
   public class UI
   {
      public InvoiceService _service =  new InvoiceService();
      public void FilterInvoices()
      {
            var query =
                   (
                     from i in _service.GetInvoices()
                     from s in _service.GetStatuses()
                     where i.ProjectID == _projectid &&
                           s.ID == i.Status
                     select new
                     {
                         InvoiceID = i.ID,
                         DocumentTotal = i.TotalDue.ToString(),
                         Created = i.Created,
                         WeekEnding = i.WeekEnding,
                         Status = s.staStatus
                     }
                   ).Skip(_pageIndex * _pageSize).Take(_pageSize);

      }

   }
{

所以我想从我的服务中返回 IQueryable,这样我就可以 从客户端代码中过滤。但我想出的问题 是 FilterInvoices 方法错误与“不支持 翻译为 sql”,因为 GetInvoice 方法 用于返回 Invoice 实体(这是 LInq2 sql 层上的一层)而不是 Linq2sql Invoice 实体。

那么如何使用这种结构从我的服务中返回一个 IQueryable? 另外,我如何在存储库 GetInvoices 中排序并返回 IQureyable。

希望这是有道理的。

马尔科姆

【问题讨论】:

    标签: c# linq-to-sql architecture


    【解决方案1】:

    linq2sql 认为 GetInvoice(在 GetInvoices 中)是一个存储过程。一种解决方法

    var query = from inv in _dbctx.Invoices orderby inv.invInvoiceDate descending select inv ;
    

    虽然这会传回由您的数据上下文生成的对象。如果您想填充自定义对象,您可以迭代集合,创建自定义 Invoice 对象并填充它们。

    foreach(var inv in query) { somelist.Add(new MyCustomInvoince() { id = inv.id ... }
    

    编辑:上面将返回一个列表。使用以下返回 IQueryable

    return from item in query
        select GetInvoice(item);
    

    不同之处在于您在此阶段使用的是 Linq2Objects,并且该提供程序将知道如何调用 GetInvoice

    【讨论】:

      【解决方案2】:

      无法查询使用 LTS(Linq to SQL)构建在 LTS 层“顶部”的东西。 原因是 LTS 实体层是数据库内容的映射,而您执行的查询“只是”翻译成 SQL。

      我个人使用另一种方法来保持我的层之间的独立性......

      我创建与我的 LTS 实体匹配的 接口,并使用 Cast() 方法让我的存储库返回接口而不是具体实现。

      效果很好。

      您需要扩展基础实体(没有 pb,因为它是部分类):

      partial class Employee : IEmployee
      

      并且您需要在您的存储库中使用此属性:

      public IQueryable<IEmployee> Query
      {
          get
          {
              return this._context.Employees.Cast<IEmployee>();
      
          }
      }
      

      基于此,您可以编写通用存储库,但这是另一回事(更复杂)

      【讨论】:

        【解决方案3】:

        这只是我的想法,但你可以尝试:

        from i in _service.GetInvoices().AsEnumerable()
        

        【讨论】:

        • 为什么转换为 IEnumarable 支持转换为 SQL 比 IQueryable 更好?
        • 不,问题出在 GetInvoices 内部。 linq 正在尝试将 GetINvoice(inv) 转换为存储过程调用
        猜你喜欢
        • 1970-01-01
        • 2017-04-12
        • 2012-01-09
        • 2019-09-11
        • 1970-01-01
        • 2019-11-23
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        相关资源
        最近更新 更多