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

eol*_*dre 5 linq extension-methods encapsulation linq-to-sql

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

Customer
    CustomerId
    FirstName
    LastName
    AddressId

Address
    AddressId
    Street
    City
    State
    Zip
Run Code Online (Sandbox Code Playgroud)

您可以构造一个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();

}
Run Code Online (Sandbox Code Playgroud)

现在让我们说你想要解释邮件地址的逻辑.您可以实现的两种方法是向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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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();

}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ric*_*ein 3

我知道这并不完全是您想要的,但您可以这样做:

var options = new DataLoadOptions();
options.LoadWith<Customer>(c => c.Address);
db.LoadOptions = options;
Run Code Online (Sandbox Code Playgroud)

然后,当客户检索地址时,它只会进行一趟。