Dotnet EF核心皇宫串包含在一个列表中分割字符串通过的逗号

0

的问题

我有一个这样的模型中的数据库:

后(帐子id int,Userid varchar(最大值)),例如员额(12,"1,2,3,7,9,20")

我想要查询的用户名,现在,我用这个:

DBContext.Posts.Where(_ => _.UserIds.Contains(targetId)).ToList();

但问题是,如果目标是1,它也返回后与Userid="15、16的" 我尝试使用Regex喜欢 Regex.IsMatch(_.UserIds, $"\\b{targetId}\\b") 但SQL不能把它翻译。

任何方法来解决这种情况下?

2
1

那么你的数据库有一个表填充 Posts. 每 Post 似乎是发布的零或更多(或许一个或多个)的用户。 在我看来,你也有一个表 Users. 每 User 已经发布的零或更多 Posts.

在我看来,有许多对多关系 UsersPosts:每个用户都已经张贴为零或更多员额;每一个职位已经公布的零(一个吗?) 或更多的用户。

通常在一个数据库将实施一个"多对多"的关系有一个特别表:结表。

你不使用结表。 你的数据库是不正常化。 也许你目前的问题是可以解决没有改变的数据库,但是我看到这么多的问题你必须要解决,也许现在不行,但在不久的将来:什么巨大的工作需要做,如果你想要删除的用户? 如何做你得到所有"员额,用户[10]发布了"那么,如果用户[10]不想提到了在出版物清单后[23]? 如何防止用户[10]提到的两次后[23]:

UserIds = 10, 3, 5, 10, 7, 10

正常的数据库

考虑到更新的数据库联接表和摆脱了串列 Post.UserIds. 这样就解决了所有这些问题。

class User
{
    public int Id {get; set;}
    public string Name {get; set;}
    ...

    // every user has posted zero or more Posts:
    public virtual ICollection<Post> Posts {get; set;}
}

class Post
{
    public int Id {get; set;}
    public string Title {get; set;}
    public Datetime PublicationDate {get; set;}
    ...

    // every Post has been posted by zero or more Users:
    public virtual ICollection<User> Users {get; set;}
}

结表:

public UsersPost
{
    public int UserId {get; set;}
    public int PostId {get; set;}
}

注:[UserId,帐子id]是独一无二的。 使用这一主键

在实体框架的列表代表非虚拟的性质。 虚拟性质反映的关系表之间(的一对-很多,很多-对-很多)

注:外国关键的是一个真正的列表,因此一外国的关键是非虚拟的。

要配置多对多,可以使用流利API:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // User - Post: many-to-many
    modelBuilder.Entity<User>()
            .HasMany<Post>(user => user.Posts)
            .WithMany(post => post.Users)
            .Map(userpost =>
                    {
                        userpost.MapLeftKey(nameof(UserPost.UserId));
                        userpost.MapRightKey(nameof(UserPost.PostId));
                        userpost.ToTable(nameof(UserPost));
                    });

    // primary key of UserPost is a composite key:
    modelBuilder.Entity<UserPost>()
        .HasKey(userpost => new {userpost.UserId, userpost.PostId});
}

回到你的问题

一旦你已经实现的结表数据请求将是容易的:

int userId = ...

// get this User with all his Posts:
var userWithPosts= dbContext.Users
    .Where(user => user.Id == userId)
    .Select(user => new
    {
         // Select only the user properties that you plan to use
         Name = user.Name,
         ...

         Posts = user.Posts.Select(post => new
         {
             // Select only the Post properties that you plan to use
             Id = post.Id
             PublicationDate = post.PublicationDate,
             ...
         })
         .ToList(),
    });

或者,如果你不想要任何用户的数据,开始与员额:

var postsOfUser = dbContext.Posts
    .Where(post => post.Users.Any(user => user.Id == userId))
    .Select(post => new {...});

有些人不喜欢使用虚拟ICollections,或者他们使用一个版本的实体的框架,该框架不支持这一点。 在这种情况下,只有做到的加入自己:

int userId = ...
var postsOfThisUser = dbContext.UserPosts

    // keep only the UserPosts of this user:
    .Where(userPost => post.UserId == userId)

    // join the remaining UserPosts with Posts
    .Join(dbContext.Posts,

    userpost => userpost.PostId,    // from every UserPost get the foreign key to Post
    post => post.Id,                // from every Post, get the primary key

    // parameter resultSelector: from every UserPost with matching Post make one new
    (userPost, post) => new
    {
        Title = post.Title,
        PublicationDate = post.PublicationDate,
        ...
    }
}

解决方案没有规范化的数据库

如果你真的不能说服你的项目领导人,一个适当的数据库,将防止一个很大的问题,在未来,考虑到创建一个SQL的文本,获得适当的员额。

你的代码的第代表当前的执行情况的数据库。 它描述表和之间的关系表。 加入一个方法来获取职位的用户,似乎我一个合法的方法代码的第.

我SQL是有点生疏,你就会知道更好的方式比我如何做到这一SQL。 我猜你会得到的要点:

public IEnumerable<Post> GetPostsOfUser(int userId)
{
    const string sqlText = "Select Id, ... from Posts where ..."

    object[] parameters = new object[] {userId};
    return this.Database.SqlQuery(sqlText, parameters);
}
2021-11-23 11:09:01

谢谢你的回答。 是的,它会很容易,如果我正常化的数据库,但这是一个古老的系统,我只是做了一个简单的例子来说明问题,我进入,在项目这一领域涉及到很多东西,需要更多的时间来重构,同时我只是想修补程序。 无论如何,谢谢你的回答。
Jihai
1

这是一个可能的解决方案如果你不可能正常化:

var sql = "select PostId,UserIds from Post";
sql += $" outer apply string_split(UserIds,',') where value={targetId}";

DBContext.Posts.FromSqlRaw(sql).ToList();
2021-11-23 18:13:09

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................