通过扩展方法将linq中的逻辑封装到sql查询中

时间:2010-10-14 16:11:04

标签: linq linq-to-sql extension-methods encapsulation

在LINQ to SQL .dbml文件中给出两个具有以下特性的类。

Customer
    CustomerId
    FirstName
    LastName
    AddressId

Address
    AddressId
    Street
    City
    State
    Zip

您可以构建一个LINQ查询,如下所示。

using(var db = new MyDataContext())
{
    results = db.Customers
        .Where(c => c.LastName.BeginsWith("o"))
        .Select(c => new
            {
                c.CustomerId,
                MailingAddress = c.FirstName + " " 
                    + c.LastName 
                    + Environment.NewLine 
                    + c.Address.Street 
                    + Environment.NewLine 
                    + c.Address.City + ", " 
                    + c.Address.State + " " 
                    + c.Address.Zip
            }).ToList();

}

现在让我们说你想要解释邮寄地址的逻辑。您可以实现的两种方法是向Customer类添加新属性,或者创建扩展方法。

public static class CustomerExtensions
{
    public static string GetMailingAddress(this Customer cust)
    {
        return cust.FirstName + " "
                    + cust.LastName
                    + Environment.NewLine
                    + cust.Address.Street
                    + Environment.NewLine
                    + cust.Address.City + ", "
                    + cust.Address.State + " "
                    + cust.Address.Zip;
    }
}

public partial class Customer
{
    public string MailingAddress
    {
        get
        {
            return this.FirstName + " "
                    + this.LastName
                    + Environment.NewLine
                    + this.Address.Street
                    + Environment.NewLine
                    + this.Address.City + ", "
                    + this.Address.State + " "
                    + this.Address.Zip;
        }
    }
}

你现在可以使用其中一种,你会得到正确的结果

using(var db = new MyDataContext())
{
    results = db.Customers
        .Where(c => c.LastName.BeginsWith("o"))
        .Select(c => new
            {
                c.CustomerId,
                c.MailingAddress, //new property
                Address2 = c.GetMailingAddress() // new extension method
            }).ToList();

}

这两种方法的问题在于,这样做会导致为您检索的每一行进行额外的数据库往返。初始查询将从Customer表中提取信息,然后在评估邮件地址时,需要单独评估每个地址记录。

有没有办法封装这个逻辑并将其绑定到客户类,以便您不需要额外往返数据库?

我认为必须有一些方法来创建一个扩展方法,而不是返回一个表达式而不是字符串。我对吗?如果是这样,我该怎么做?

1 个答案:

答案 0 :(得分:3)

我知道这不是你想要的,但你可以这样做:

var options = new DataLoadOptions();
options.LoadWith<Customer>(c => c.Address);
db.LoadOptions = options;

然后只有一次旅行,因为与客户一起检索地址。