尝试显式键入LINQ Select方法的结果

时间:2015-11-08 23:01:50

标签: c# linq linq-to-entities

我仍然试图围绕LINQ to Entities方法的一些细微差别。使用下面的代码块,我通常使用类型var作为对象(下面的注释1),但因为foreach循环没有嵌套在switch/case块中(注释2)我需要在emailList块之外定义switch/case的类型,我需要明确定义它(var不再是一个选项)。那么emailList的正确类型是什么?编译器不喜欢IQueryable<vwMaterialsDueAutoEmail>。此外,当Emailstate为CancelNotice(下面的注释3)时,IQueryable<vwMaterialsDueAutoEmail>的类型将不起作用。编译器似乎喜欢IQueryable(下面的注释4),没有泛型类型<T>,但是当我在foreach中使用try emailList时,我没有结果,并且所有尝试都在检索一个email属性(email.CaseNameemail.EmailAddress ...)惨遭失败(下面的评论5)。我80%确信修复程序正确键入emailList并且在为其分配值时可能会使用某种类型的强制转换,但我不确定如何将其删除。

   IQueryable emailList; // Comment 4: IQueryable with no <Type>
   string subject;
   string body = System.IO.File.ReadAllText(parameters.EmailBodyPath() + 
      @"\" + parameters.EmailBodyFile());
   switch (parameters.EmailState)
   {
      case EmailState.MaterialsDue:
         emailList = context.vwMaterialsDueAutoEmail.Select(d => new 
         // Comment 1: Normally I'd use var emailList.
         {
            CaseID = d.CaseID,
            CaseName = d.CaseName,
            EmailAddress = d.EmailAddress
         });
         break;
      case EmailState.CancelNotice: //Comment 3: The other possible case.
         emailList = context.vwRTCancelNoticeEmails.Select(d => new 
         // Omitted. Code similar to MaterialsDue.
      default:
         emailList = context.vwMaterialsDueAutoEmail; 
         // Will never be executed. Existence prevents "Use of unassigned variable" erorr 
         break; 
   }
   foreach (var email in emailList) 
   // Comment 2: foreach is not in the switch/case block above
   {
      subject = "Materials Due: " + email.CaseName;
      body = body.Replace("_CaseName_", email.CaseName);
      //Comment 5: email problematic
      SendEmail(email.EmailAddress, subject, "This is the body.");
   }

2 个答案:

答案 0 :(得分:1)

执行new { Property = value... }时,您使用的是匿名类型。而且一个匿名类型显然没有名字。由于类型没有名称,因此无法明确定义。 (官方它有一个名字,但是那个由编译器分配......)

此外,由于您在不同位置使用匿名类型,因此所有这些类型都会有所不同,因此很难将它们分配到同一emailList,因为emailList需要一次是三种类型。

解决方案可以是创建您自己的KNOWN类型,使用参数CaseIDCaseName等定义。在Select方法中使用此类型,然后可以定义emailListIQueryable<MyKnownType>

答案 1 :(得分:0)

创建一个界面,表示可以通过电子邮件通知的类型

public interface IEmailNotifiable
{
    EmailContent Content {get;} 
}

然后将IQueryable emailList;更改为IQueryable<IEmailNotifiable>;

然后创建一些实现此接口的其他类,您可以在select语句中构建它。

emailList = context.vwMaterialsDueAutoEmail.Select(d => new 
        MaterialsDueEmailNotification(d.CaseID, d.CaseName, d.EmailAddress));

只要MaterialsDueEmailNotification实现IEmailNotifiable,就可以有效地转换,因为IQueryable<T>是协变的。

然后:

foreach (var email in emailList) 
{
    SendEmail(email.Content);
}

现在我不仅解决了类型问题,而且还将电子邮件的确切内容结构下放到适当的类中,因此从理论上讲,电子邮件的内容和结构可能因类而异。创建