Dotnet EF 핵심 Linq 문자열이 포함되어 목록에서 문자열에 의해 분할 쉼표

0

질문

나는 모델은 다음과 같이 데이터베이스에서:

포스트(PostId int,UserIds varchar(MAX)),예후(12,"1,2,3,7,9,20")

내가 원하는 쿼리하는 사용자 Id 에 의해,지금,나는 사용:

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

하지만 문제는 경우에는 대상은 1,그것은 또한 반환 후으로 사용자 Id="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,PostId]가 유일하다. 사용은 기본 열쇠

Entity framework 에서는 열의 테이블에 의해 표현된 비상 속성입니다. 가상 속성을 반영하 사이의 관계 테이블(one-to-many,many-to-many)

참고:외국인이 실제 테이블에 열고,따라서 외국인 핵심 비상.

을 구성하는 다 사용할 수 있습니다,유창한 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 텍스트는 적절한 게시물에 대한 당신.

귀하의 DbContext 나타내는 현재 구현의 데이터베이스입니다. 그것을 설명하는 테이블과 테이블 사이의 관계 테이블이 있습니다. 를 추가하는 방법을 가져오는 게시물의 사용자가 날 것으로 보인다 합법적 방법에 대한 DbContext.

나의 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ý
..................................................................................................................