簡體   English   中英

LINQ-添加記錄,其中嵌套的值包含來自另一個數組的值

[英]LINQ - Adding record where nested value contains value from another array

我正在使用Entity Framework和LINQ向使用SQL數據庫的用戶添加通知記錄。 我的用戶已經具有他們選擇的嵌套標簽數組。 如果用戶選擇的標簽包含我傳遞給我的方法的數組標簽中包含的任何標簽,我想向用戶添加通知記錄。

這是我的Tag數組的樣子:

[
  {
    "Id": 2,
    "Text": "Blue",
    "Value": "blue"
  },
  {
    "Id": 4,
    "Text": "Red",
    "Value": "red"
  },
  {
    "Id": 3,
    "Text": "White",
    "Value": "white"
  }
]

我的通知如下所示:

{
    "Image": "https://www.image.com",
    "Heading": "Example heading",
    "Content": "Example content"
}

我的用戶有一個與其關聯的嵌套標簽數組,該數組看起來也類似於上面的標簽數組,並且具有相同的ID。

我的方法目前是這樣的:

AddUserNotification(Notification notification, IList<Tag> tags) 
{
    var usersToAddTheNotificationTo = DbContext.Users
        .Where(User.Tags.Contains(tags)).ToList();

    foreach(var user in usersToAddTheNotificationTo) 
    {
          user.Notifications.Add(notification);
    }
}

如何實現這是最簡單的方法?

您想要做的是在用戶標簽和通知標簽之間建立交集 ,並且如果此新交集數量不為空,則要添加通知

var usersToAddTheNotificationTo = DbContext.Users
        .Where(User.Tags.Intersect(tags).Count() > 0).ToList();

您可能會遇到關聯標記的問題,這些標記不是與當前上下文或查詢關聯的實體。 另外,Notification是新實體,還是代表數據庫中已經存在的記錄? 是否希望上下文知道這一點?

當尋求基於條件進行關聯時,我通常會選擇使用ID,因為這樣可以更輕松地查詢匹配項。 例如:

public void AddUserNotification(Notification notification, IList<int> tagIds) 
{
    var usersToAddTheNotificationTo = DbContext.Users
        .Where(x => x.Tags.Any(t => tagIds.Contains(t.TagId)).ToList();

    foreach(var user in usersToAddTheNotificationTo) 
    {
          user.Notifications.Add(notification);
    }
}

在不更改簽名的情況下:

public void AddUserNotification(Notification notification, IList<Tag> tags) 
{
    var tagIds = tags.Select(x => x.TagId).ToList();
    var usersToAddTheNotificationTo = DbContext.Users
        .Where(x => x.Tags.Any(t => tagIds.Contains(t.TagId)).ToList();

    foreach(var user in usersToAddTheNotificationTo) 
    {
          user.Notifications.Add(notification);
    }
}

另一種警告:如果Notification表示一個現有記錄,那么您還應該根據ID從上下文中加載它。

var existingNotification = DbContext.Notifications.Single(x => x.NotificationId == notification.NotificationId);

傳遞給控制器​​動作之類的實體是反序列化的,因此就DbContext而言,它們與以下代碼沒有區別:

var notification = new Notification { NotificationId = 16, .... };

早先從DbContext加載通知都沒關系。 這是一個不同的DbContext實例,並且該實體已序列化和反序列化。 EF會將其視為新記錄。 如果PK被配置為身份,您將獲得一條插入了新NotificationID的新記錄。 如果未配置PK,則在EF嘗試插入重復行時會遇到密鑰沖突。 您可以使用Attach()其與DbContext關聯,並將State設置為“ Modified”,但這會使您的系統面臨很大的篡改風險,因為客戶端可能會以您不希望的方式更改該實體,更改FK或您的其他值UI不允許並覆蓋數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM