简体   繁体   English

LINQ-添加记录,其中嵌套的值包含来自另一个数组的值

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

I'm looking to add a notification record to my users with an SQL database using Entity Framework and LINQ. 我正在使用Entity Framework和LINQ向使用SQL数据库的用户添加通知记录。 My users already have a nested array of tags that they have chosen. 我的用户已经具有他们选择的嵌套标签数组。 I would like to add a notification record to a user if their chosen tags contain any tag that is included in the array tags i pass into my method. 如果用户选择的标签包含我传递给我的方法的数组标签中包含的任何标签,我想向用户添加通知记录。

This is what my Tag array looks like: 这是我的Tag数组的样子:

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

My Notification looks like this: 我的通知如下所示:

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

My users have a nested array of tags associated with them that also looks like tags array above and have the same id's. 我的用户有一个与其关联的嵌套标签数组,该数组看起来也类似于上面的标签数组,并且具有相同的ID。

My method is currently like this: 我的方法目前是这样的:

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);
    }
}

How can I achieve this is the most simple way? 如何实现这是最简单的方法?

what you want to do is building an intersection between the user's tags and the notification's tags and you want to add the notification if this new intersection quantity is not empty 您想要做的是在用户标签和通知标签之间建立交集 ,并且如果此新交集数量不为空,则要添加通知

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

You may run into issues associating Tags where these are not entities associated with the current context or query. 您可能会遇到关联标记的问题,这些标记不是与当前上下文或查询关联的实体。 Also, is the Notification a new entity, or does it represent a record that already exists in the database? 另外,Notification是新实体,还是代表数据库中已经存在的记录? Is the context expected to know about it? 是否希望上下文知道这一点?

When looking to associate based on criteria, I generally opt for working with IDs as this makes it simpler to query for matches. 当寻求基于条件进行关联时,我通常会选择使用ID,因为这样可以更轻松地查询匹配项。 For example: 例如:

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);
    }
}

Without changing the signature: 在不更改签名的情况下:

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);
    }
}

One other caution: If Notification represents an existing record then you should also load it from the context based on the ID. 另一种警告:如果Notification表示一个现有记录,那么您还应该根据ID从上下文中加载它。

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

Entities passed in to things like Controller actions are deserialized, so as far as a DbContext is concerned they are no different to code like: 传递给控制器​​动作之类的实体是反序列化的,因此就DbContext而言,它们与以下代码没有区别:

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

It doesn't matter that earlier the notification was loaded from a DbContext. 早先从DbContext加载通知都没关系。 It was a different DbContext instance, and the entity was serialized and deserialized. 这是一个不同的DbContext实例,并且该实体已序列化和反序列化。 EF will treat it as a new record. EF会将其视为新记录。 If the PK is configured as an Identity, you will get a new record inserted with a new NotificationID. 如果PK被配置为身份,您将获得一条插入了新NotificationID的新记录。 If the PK isn't configured, you'll get a key violation as EF attempts to insert a duplicate row. 如果未配置PK,则在EF尝试插入重复行时会遇到密钥冲突。 You can associate it to the DbContext using Attach() and set the State to "Modified" but this opens your system to a significant risk of tampering as clients could alter that entity in ways you don't expect, changing FKs or other values your UI doesn't permit and overwrite the data. 您可以使用Attach()其与DbContext关联,并将State设置为“ Modified”,但这会使您的系统面临很大的篡改风险,因为客户端可能会以您不希望的方式更改该实体,更改FK或您的其他值UI不允许并覆盖数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM