如何重构 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);

这会将查询的整个部分保留在服务器端,就像您在每个查询中都写出来一样。