c#使用Linq将数组中的数组投影到新数组上?
我正在使用.NETCore并构建一个API。我有一个传入的JSON,我正在将其映射到C#对象,在大多数情况下,JSON非常简单,除了一个部分可能在数组中有一个数组,请参见下面:c#使用Linq将数组中的数组投影到新数组上?,c#,arrays,entity-framework,linq,C#,Arrays,Entity Framework,Linq,我正在使用.NETCore并构建一个API。我有一个传入的JSON,我正在将其映射到C#对象,在大多数情况下,JSON非常简单,除了一个部分可能在数组中有一个数组,请参见下面: "marketing_preferences": [ { "channel": "EDM", "opt_in": false, "valid_from_date": "2020-05-30T07:07:53.723Z", "content_type_preferences": [
"marketing_preferences": [
{
"channel": "EDM",
"opt_in": false,
"valid_from_date": "2020-05-30T07:07:53.723Z",
"content_type_preferences": [
{
"type": "CAT",
"opt_in": false,
"valid_from_date": "2020-05-30T07:07:53.724Z"
},
{
"type": "TAC",
"opt_in": true,
"valid_from_date": "2020-05-30T07:07:53.724Z"
}
]
},
{
"channel": "SMS",
"opt_in": true,
"valid_from_date": "2020-05-30T07:07:53.724Z",
"content_type_preferences": []
},
{
"channel": "SM",
"opt_in": true,
"valid_from_date": "2020-05-30T07:07:53.724Z",
"content_type_preferences": []
}
]
营销首选项可能(但可能不)包含一个或多个内容类型首选项。因此,marketing_preferences是一个数组,content_type_preferences是该数组中的一个可选数组。在我的代码中映射或投影营销偏好非常简单:
customer.MarketingPreferences = source.RequestCustomer.MarketingPreferences
.Select(x => new MarketingPreferences()
{
ChannelId = x.Channel,
OptIn = x.OptIn,
ValidFromDate = x.ValidFromDate,
UpdatedBy = Functions.DbUser,
CreatedDate = DateTime.UtcNow,
UpdatedDate = DateTime.UtcNow,
UpdatingStore = null // Not passed by API
})
.ToList();
然而,我有点拘泥于将content\u type\u首选项投影到其等效对象的语法。以下是我尝试投影到的类:
public partial class MarketingPreferences
{
public MarketingPreferences()
{
ContentTypePreferences = new HashSet<ContentTypePreferences>();
}
public Guid CustomerInternalId { get; set; }
public string ChannelId { get; set; }
public bool? OptIn { get; set; }
public DateTime? ValidFromDate { get; set; }
public string UpdatedBy { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? UpdatedDate { get; set; }
public string UpdatingStore { get; set; }
public virtual Customer CustomerInternal { get; set; }
public virtual ICollection<ContentTypePreferences> ContentTypePreferences { get; set; }
}
我确实开始恢复到一种笨拙的方式,但我真的不满意,我更愿意尝试找到一种灵巧的方式来实现以下目标:
foreach (var marketingPrefs in source.RequestCustomer.MarketingPreferences)
{
if (marketingPrefs.ContentTypePreferences.Length > 0)
{
Console.WriteLine($"marketing preference: {marketingPrefs.Channel}");
foreach (var contentPrefs in marketingPrefs.ContentTypePreferences)
{
Console.WriteLine($"content preference: {contentPrefs.Type}");
customer.ContentTypePreferences.Add(new ContentTypePreferences
{
TypeId = contentPrefs.Type,
OptIn = contentPrefs.OptIn,
ValidFromDate = contentPrefs.ValidFromDate
});
}
}
}
简单应该足以使集合扁平化:
customer.ContentTypePreferences = source.RequestCustomer.MarketingPreferences
.SelectMany(mp => mp.ContentTypePreferences)
.Select(contentPrefs => new ContentTypePreferences
{
TypeId = contentPrefs.Type,
OptIn = contentPrefs.OptIn,
ValidFromDate = contentPrefs.ValidFromDate
})
.ToList();
我确实找到了一种方法来解决这个问题,使用下面的方法
customer.MarketingPreferences = source.RequestCustomer.MarketingPreferences
.Select(x => new MarketingPreferences()
{
ChannelId = x.Channel,
OptIn = x.OptIn,
ValidFromDate = x.ValidFromDate,
UpdatedBy = Functions.DbUser,
CreatedDate = DateTime.UtcNow,
UpdatedDate = DateTime.UtcNow,
ContentTypePreferences = (from c in x.ContentTypePreferences
select new ContentTypePreferences
{
TypeId = c.Type,
OptIn = c.OptIn,
ValidFromDate = c.ValidFromDate,
ChannelId = x.Channel // Should inherit parent marketing preference channel
}).ToList(),
UpdatingStore = null // Not passed by API
})
.ToList();
我很欣赏其他答案,但我意识到仅仅平展可能还不够,因为每个ContentTypePreference的ChannelId并没有随POST JSON一起传递,而是源自该ContentTypePreference的父MarketingTypePreference(例如,电子邮件的子级将具有电子邮件的频道Id)因此,在为Entity Framework创建每个新的ContentTypePreferences时,上面的解决方案允许我注入这一点。SelectMany有效吗?嗨,mjwills,你能用一个例子来说明你的意思吗?这是否回答了你的问题?
customer.MarketingPreferences = source.RequestCustomer.MarketingPreferences
.Select(x => new MarketingPreferences()
{
ChannelId = x.Channel,
OptIn = x.OptIn,
ValidFromDate = x.ValidFromDate,
UpdatedBy = Functions.DbUser,
CreatedDate = DateTime.UtcNow,
UpdatedDate = DateTime.UtcNow,
ContentTypePreferences = (from c in x.ContentTypePreferences
select new ContentTypePreferences
{
TypeId = c.Type,
OptIn = c.OptIn,
ValidFromDate = c.ValidFromDate,
ChannelId = x.Channel // Should inherit parent marketing preference channel
}).ToList(),
UpdatingStore = null // Not passed by API
})
.ToList();