代码之家  ›  专栏  ›  技术社区  ›  derek

LINQ to SQL Web应用程序最佳实践

  •  14
  • derek  · 技术社区  · 16 年前

    在我构建web应用程序的经验中,我一直使用n层方法。从数据库获取数据并填充对象的DAL,从DAL获取对象并对其执行所需的任何业务逻辑的BLL,以及从BLL获取其显示数据的网站。 我最近开始学习LINQ,大多数示例都显示了从Web应用程序代码后面出现的查询(可能我只看到过过于简化的示例)。在n层体系结构中,这一直被视为一个大禁忌。

    使用linqtosql创建Web应用程序解决方案的一般架构最佳实践或方法是什么?

    2 回复  |  直到 16 年前
        1
  •  16
  •   Steven    11 年前

    恐怕你确实看到过过于简化的例子。LINQtoSQL(System.Data.LINQ)是DAL层。L2S生成的类是您的域(但不要与 Domain-Driven Design

    我总是试图防止LINQ泄漏到SQL DataContext 数据上下文 . 你也不应该回来 IQueryable<T> 对象到表示层。在IMO中,业务层应该完全控制 数据上下文 (工作单元)和SQL查询的形状。

    不过,有几种口味。有些人为了放松这些限制而搭帐篷。其他人甚至走得更远。这取决于你自己的口味和应用程序的大小。应用程序越大,就越有理由添加抽象层。

    不允许时 IQueryable 离开业务层之后,您将面临一些有趣的挑战。例如,表示层必须指示业务层如何对结果进行排序。虽然您可以让表示层自己对结果进行排序,但这意味着您必须从表示层的数据库和页面获取所有数据,这将导致系统性能非常差。这个问题有几种解决办法。在所有情况下,您都需要通知业务层如何为您排序结果。当您搜索 LINQ dynamic sort . 我自己也写过这样的解决方案, here .

    液体 离开BL将带来的问题是域对象通常也不能离开BL。大多数LINQ to SQL域对象将包含延迟加载的属性(例如,到其他域对象的集合)。然而,当 数据上下文 在将结果返回到表示层之前,它将被释放。当表示访问延迟加载的属性时,会发生异常,因为 数据上下文 已处理。当你处理 数据上下文 在您的业务层中,这种行为当然是“设计的”。允许表示层获得延迟加载的属性意味着BL将失去对发送到数据库的查询的控制,从而失去对性能的控制。

    要解决这个问题,您应该将数据传输对象(DTO)从BL返回到表示层。DTO只包含数据和 数据上下文 ,并且没有延迟加载的属性。DTO可以针对手头的实际请求进行特殊格式化。dto本身当然会导致编码开销,因此系统的大小和性能需求必须证明这一点。为了方便自己,我倾向于将静态投影方法放在DTO上。虽然这不符合 separation of concerns

    public class CustomerDTO
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
        // City is flatterned from Address.City.
        public string City { get; set; }
    
        internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers)
        {
            return
                from customer in customers
                select new CustomerDTO()
                {
                    CustomerId = customer.Id, 
                    Name = customer.Name,
                    City = customer.Address.City
                };
        }
    }
    

    AsDTO 方法,该方法能够转换 Customer CustomerDTO DTO公司。这使得将域对象转换为dto更加容易。例如,看一下这个BL方法:

    public static CustomerDTO[] GetCustomersByCountry(string country)
    {
        using (var db = ContextFactory.CreateContext())
        {
            IQueryable<Customer> customers =
                (from customer in db.Customers
                where customer.Address.Country == country
                orderby customer.Name, customer.Id);
    
            return CustomerDTO.AsDTO(customers).ToArray();
        }
    }
    

    这种方法的优点是,当您查看SQL查询时,您将看到只有customer Id、Name和Address表的City将从数据库中检索。这是因为 AsDTO公司 方法转换一 液体

    我希望这能给你一些建议。当然,这是我对这个问题的看法,也是我发现在我的情况下可行的事情。

        2
  •  4
  •   Chris O    16 年前

    如果要在DAL和BLL之间进行分离,linqtosql是DAL实现中的DB访问。如果您有不太复杂的Web应用程序(而且也从不打算切换DB后端),那么您就可以不用显式的DAL/BLL,而是在代码背后完成所有工作。linqtosql对于只读操作非常有效,但是对于实现写操作来说,感觉需要做更多的工作。

    推荐文章