通过扩展方法将逻辑封装在 linq to sql 查询中
给定 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我知道这并不完全是您想要的,但您可以这样做:
然后,当客户检索地址时,它只会进行一趟。
I know this isn't exactly what you are looking for, but you can do this:
Then it will only make one trip as the Address is retrieved with the Customer.