如何重构 LINQ 查询
How to refactor LINQ query
我有以下代码:
result = from i in _dbContext.Meetings
where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && //!i.IsTex &&
DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInviter.FirstName + " " + i.UserInviter.LastName,
Company = i.UserInviter.Company,
Company2 = i.UserInvited.Company,
MeetingID = i.MeetingID,
Time = DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value,
CreatedTime = i.dateCreated,
Image = i.UserInviter.ProfileImage,
TableNumber = i.TableNumber,
Username = i.UserInviter.aspnet_User.UserName,
Username2 = i.UserInvited.aspnet_User.UserName,
UsernameInviter = i.UserInviter.aspnet_User.UserName,
RequestText = i.RequestText,
NoteInviter = i.NoteInviter,
ResendInvitationCount = (i.ResendInvitationCount.HasValue) ? i.ResendInvitationCount.Value : 0,
NoteInvited = i.NoteInvited,
MeetingType = i.MeetingType.TypeName
};
我使用了很多这样的扩展,只是做了不同的修改,但每个扩展都有相同的部分select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()....
。
即
result = from i in _dbContext.Meetings
where i.UserInviterID == CurrentUserID && i.MeetingStatus == null && !i.IsTex && DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where i.UserInviterID == CurrentUserID && i.MeetingStatus == null && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInvited.FirstName + " " + i.UserInvited.LastName,
//...
};
result = from i in _dbContext.Meetings
where (i.UserInviterID == CurrentUserID) && i.MeetingStatus == true && !i.IsTex && DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where (i.UserInviterID == CurrentUserID) && i.MeetingStatus == true && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInvited.FirstName + " " + i.UserInvited.LastName,
//...
};
我可以将这部分设置为变量以在所有其他扩展中使用吗?
是的,您可以为您创建一个 returns 一个 ITW2012Mobile.Core.DataTable.MeetingModel2Tmp
的方法,然后在 select 中调用该方法。
类似于
private ITW2012Mobile.Core.DataTable.MeetingModel2Tmp MethodName(TypeOfI i)
{
return new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp() {
//same stuff as in your question's initializer
};
}
并用
调用它
result = from i in _dbContext.Meetings
where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && //!i.IsTex &&
DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select MethodName(i);
无论如何,查询都会被编译成 LINQ 扩展方法,.Select()
takes in a Func<TSource, TResult>
as an argument. A Func 只是一个具有一个输入参数(TSource
类型)和 returns 的委托(方法)一个 TResult
对象。
您需要放弃 LINQ 查询语法,直接调用 Select
方法。那应该没什么大不了的。如果这样做,您可以将查询的投影部分存储在单独的变量中。
Expression<Func<Meeting, ITW2012Mobile.Core.DataTable.MeetingModel2Tmp>> projection = i =>
new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInviter.FirstName + " " + i.UserInviter.LastName,
Company = i.UserInviter.Company,
Company2 = i.UserInvited.Company,
MeetingID = i.MeetingID,
Time = DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value,
CreatedTime = i.dateCreated,
Image = i.UserInviter.ProfileImage,
TableNumber = i.TableNumber,
Username = i.UserInviter.aspnet_User.UserName,
Username2 = i.UserInvited.aspnet_User.UserName,
UsernameInviter = i.UserInviter.aspnet_User.UserName,
RequestText = i.RequestText,
NoteInviter = i.NoteInviter,
ResendInvitationCount = (i.ResendInvitationCount.HasValue) ? i.ResendInvitationCount.Value : 0,
NoteInvited = i.NoteInvited,
MeetingType = i.MeetingType.TypeName
};
...
result =
(from i in _dbContext.Meetings
where i.UserInviterID == CurrentUserID
&& i.MeetingStatus == null
&& !i.IsTex
&& DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
select i).Select(projection);
这会将查询的整个部分保留在服务器端,就像您在每个查询中都写出来一样。
我有以下代码:
result = from i in _dbContext.Meetings
where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && //!i.IsTex &&
DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInviter.FirstName + " " + i.UserInviter.LastName,
Company = i.UserInviter.Company,
Company2 = i.UserInvited.Company,
MeetingID = i.MeetingID,
Time = DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value,
CreatedTime = i.dateCreated,
Image = i.UserInviter.ProfileImage,
TableNumber = i.TableNumber,
Username = i.UserInviter.aspnet_User.UserName,
Username2 = i.UserInvited.aspnet_User.UserName,
UsernameInviter = i.UserInviter.aspnet_User.UserName,
RequestText = i.RequestText,
NoteInviter = i.NoteInviter,
ResendInvitationCount = (i.ResendInvitationCount.HasValue) ? i.ResendInvitationCount.Value : 0,
NoteInvited = i.NoteInvited,
MeetingType = i.MeetingType.TypeName
};
我使用了很多这样的扩展,只是做了不同的修改,但每个扩展都有相同的部分select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()....
。
即
result = from i in _dbContext.Meetings
where i.UserInviterID == CurrentUserID && i.MeetingStatus == null && !i.IsTex && DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where i.UserInviterID == CurrentUserID && i.MeetingStatus == null && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInvited.FirstName + " " + i.UserInvited.LastName,
//...
};
result = from i in _dbContext.Meetings
where (i.UserInviterID == CurrentUserID) && i.MeetingStatus == true && !i.IsTex && DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where (i.UserInviterID == CurrentUserID) && i.MeetingStatus == true && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInvited.FirstName + " " + i.UserInvited.LastName,
//...
};
我可以将这部分设置为变量以在所有其他扩展中使用吗?
是的,您可以为您创建一个 returns 一个 ITW2012Mobile.Core.DataTable.MeetingModel2Tmp
的方法,然后在 select 中调用该方法。
类似于
private ITW2012Mobile.Core.DataTable.MeetingModel2Tmp MethodName(TypeOfI i)
{
return new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp() {
//same stuff as in your question's initializer
};
}
并用
调用它 result = from i in _dbContext.Meetings
where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && //!i.IsTex &&
DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
//where i.UserInvitedID == CurrentUserID && i.MeetingStatus == null && DbFunctions.TruncateTime(i.AllowedTime.AllowedDate.Day) >= date
select MethodName(i);
无论如何,查询都会被编译成 LINQ 扩展方法,.Select()
takes in a Func<TSource, TResult>
as an argument. A Func 只是一个具有一个输入参数(TSource
类型)和 returns 的委托(方法)一个 TResult
对象。
您需要放弃 LINQ 查询语法,直接调用 Select
方法。那应该没什么大不了的。如果这样做,您可以将查询的投影部分存储在单独的变量中。
Expression<Func<Meeting, ITW2012Mobile.Core.DataTable.MeetingModel2Tmp>> projection = i =>
new ITW2012Mobile.Core.DataTable.MeetingModel2Tmp()
{
Name = i.UserInviter.FirstName + " " + i.UserInviter.LastName,
Company = i.UserInviter.Company,
Company2 = i.UserInvited.Company,
MeetingID = i.MeetingID,
Time = DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value,
CreatedTime = i.dateCreated,
Image = i.UserInviter.ProfileImage,
TableNumber = i.TableNumber,
Username = i.UserInviter.aspnet_User.UserName,
Username2 = i.UserInvited.aspnet_User.UserName,
UsernameInviter = i.UserInviter.aspnet_User.UserName,
RequestText = i.RequestText,
NoteInviter = i.NoteInviter,
ResendInvitationCount = (i.ResendInvitationCount.HasValue) ? i.ResendInvitationCount.Value : 0,
NoteInvited = i.NoteInvited,
MeetingType = i.MeetingType.TypeName
};
...
result =
(from i in _dbContext.Meetings
where i.UserInviterID == CurrentUserID
&& i.MeetingStatus == null
&& !i.IsTex
&& DbFunctions.AddMinutes(DbFunctions.AddHours(i.MeetingTime.Day, i.MeetingTime.Hour).Value, i.MeetingTime.Minute).Value > dateWithTime
select i).Select(projection);
这会将查询的整个部分保留在服务器端,就像您在每个查询中都写出来一样。