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

发布于 2024-09-27 15:23:32 字数 2408 浏览 12 评论 0原文

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

}

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

有没有一种方法可以封装此逻辑并将其与客户类绑定在一起,这样您就不需要任何额外的数据库往返?

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

Given two classes in your LINQ to SQL .dbml file with the following properies.

Customer
    CustomerId
    FirstName
    LastName
    AddressId

Address
    AddressId
    Street
    City
    State
    Zip

You could construct a LINQ query such as the following.

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

}

Now let's say that you wanted to excapsulate the logic for putting together the mailing address. Two ways that you could accomplish that would be to add a new property to the Customer class, or create an extension method.

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;
        }
    }
}

you could now use one of those and you would get the correct results

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

}

The problem with both of these ways is that doing so will cause there to be an extra round trip to the database for each row that you retrieve. The initial query will pull back the information from the Customer table, and then it will need to grad each address record individually when it evaluates for the mailing address.

Is there a way to encapsulate this logic and tie it to the customer class in such a way that you don't need any extra round trips to the database?

I think that there must be some way to create an extension method that instead returns an expression instead of a string. Am I right? If so, how would I do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁许谁一生繁华 2024-10-04 15:23:32

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

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

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

I know this isn't exactly what you are looking for, but you can do this:

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

Then it will only make one trip as the Address is retrieved with the Customer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文