每次迭代,此查询为每个填充的地址创建一个电子邮件收件人。 没有多次迭代可以完成吗?
var addedRecipients = (from oldRecip in oldEmailRecipients
where !string.IsNullOrWhiteSpace(oldRecip.EmailAddress1)
select new EmailRecipient
{
UserName = oldRecip.UserName,
EmailAddress = oldRecip.EmailAddress1
}
).Union(from oldRecip in oldEmailRecipients
where !string.IsNullOrWhiteSpace(oldRecip.EmailAddress2)
select new EmailRecipient
{
UserName = oldRecip.UserName,
EmailAddress = oldRecip.EmailAddress2
});
您可以使用SelectMany
扩展方法:
var addedRecipients = oldEmailRecipients.SelectMany(e=>
{
var result= new List<EmailRecipient>();
if(!string.IsNullOrWhiteSpace(e.EmailAddress1))
{
result.Add(new EmailRecipient
{
UserName = e.UserName,
EmailAddress = e.EmailAddress1
});
}
if(!string.IsNullOrWhiteSpace(e.EmailAddress2))
{
result.Add(new EmailRecipient
{
UserName = e.UserName,
EmailAddress = e.EmailAddress2
});
}
return result;
});
更新
我上面展示的解决方案仅适用于 Linq to Objects。您的评论表明我正在使用 EF。一个简单的解决方案是在SelectMany
切换到 Linq to Object 之前调用AsEnumerable
方法,但如果不先筛选收件人,这可能会损害您的性能。
另一种解决方案可能是在调用SelectMany
之前仅从服务器中选择首先需要的数据,以便在这种情况下不加载不需要的其他列:
...Where(...)
.Select(r=>new{UserName=r.UserName,
EmailAddress1=r.EmailAddress1,
EmailAddress2=r.EmailAddress2 })
.AsEnumerable()
.SelectMany(...);
坚持使用查询语法,并确保只处理具有非 null/空格EmailAddress1
或非 null/空格EmailAddress2
oldEmailRecipients
项:
var addedRecipients =
from oldEmail in oldEmailRecipients
let hasEmail1 = !string.IsNullOrWhiteSpace(oldEmail.EmailAddress1)
let hasEmail2 = !string.IsNullOrWhiteSpace(oldEmail.EmailAddress2)
where hasEmail1 || hasEmail2
let emailUserNameCombos = hasEmail1 && hasEmail2
? new[]
{
new {Email = oldEmail.EmailAddress1, oldEmail.UserName},
new {Email = oldEmail.EmailAddress2, oldEmail.UserName}
}
: hasEmail1
? new[] {new {Email = oldEmail.EmailAddress1, oldEmail.UserName}}
: new[] {new {Email = oldEmail.EmailAddress2, oldEmail.UserName}}
from emailUsername in emailUserNameCombos
select new EmailRecipient
{
UserName = emailUsername.UserName,
EmailAddress = emailUsername.Email
};
您可以构建一个内联数组来添加两封电子邮件,并使用 SelectMany 将它们展平。
var addedRecipients = from oldRecip in oldEmailRecipients
let emails =
new[] {oldRecip.EmailAddress1, oldRecip.EmailAddress2}.Where(e => !string.IsNullOrWhiteSpace(e))
from email in emails
where emails.Any()
select new EmailRecipient
{
UserName = oldRecip.UserName,
EmailAddress = email
};
当您的EmailRecipient
有两个以上的电子邮件地址时,您可以这样做:
// Just building a pseudo dataclass
List<Recipient> oldEmailRecipients = Enumerable.Range(1, 10).Select(item => new Recipient()
{
Name = "Recipient" + item,
EmailAddress1 = "pseudo" + item + "@gmail.com",
EmailAddress2 = "pseudo" + (item + 1) + "@gmail.com",
//EmailAddress3 = "pseudo" + (item + 2) + "@gmail.com",
EmailAddress3 = "",
EmailAddress4 = "pseudo" + (item + 3) + "@gmail.com",
} ).ToList( )
// create anonymous object for each recipient and a list of valid adresses
var query = from mailRecipients in oldEmailRecipients
select new
{
Name = mailRecipients.Name,
Addresses = new List<string>()
{
mailRecipients.EmailAddress1,
mailRecipients.EmailAddress2,
mailRecipients.EmailAddress3,
mailRecipients.EmailAddress4
}.Where(item => string.IsNullOrEmpty( item ) == false )
};
// create an EmailRecipient for each valid combination
var final = from item in query
from address in item.Addresses
select new EmailRecipient
{
Name = item.Name,
Address = address
};