Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#使用Linq将数组中的数组投影到新数组上?_C#_Arrays_Entity Framework_Linq - Fatal编程技术网

c#使用Linq将数组中的数组投影到新数组上?

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": [

我正在使用.NETCore并构建一个API。我有一个传入的JSON,我正在将其映射到C#对象,在大多数情况下,JSON非常简单,除了一个部分可能在数组中有一个数组,请参见下面:

"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();