Dotnet एफई कोर Linq स्ट्रिंग सूची में स्ट्रिंग द्वारा विभाजित अल्पविराम

0

सवाल

मैं एक मॉडल की तरह इस डेटाबेस में:

पोस्ट (PostId पूर्णांक, UserIds varchar(MAX)), उदाहरण के लिए पोस्ट (12, "1,2,3,7,9,20")

मैं चाहता हूँ कि यह क्वेरी करने के लिए द्वारा यूजर आईडी, अब के लिए, मैं इस का उपयोग करें:

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

लेकिन समस्या यह है कि अगर लक्ष्य है 1, यह भी वापस पोस्ट के साथ UserIds = "15,16" मैं कोशिश करने के लिए Regex का उपयोग की तरह Regex.IsMatch(_.UserIds, $"\\b{targetId}\\b") लेकिन SQL अनुवाद नहीं कर सकता यह.

किसी भी तरह से हल करने के लिए इस मामले में?

2
1

तो अपने डेटाबेस में एक मेज के साथ भरा Posts. हर Post तैनात किया जा रहा है शून्य या अधिक (शायद एक या एक से अधिक) उपयोगकर्ताओं के लिए है । यह, मुझे लगता है कि आप भी एक मेज के Users. हर User पोस्ट किया गया है, शून्य या अधिक Posts.

यह मुझे लगता है कि वहाँ है एक कई-से-कई संबंध के बीच Users और Posts: हर उपयोगकर्ता पोस्ट किया गया है शून्य या एक से अधिक पदों; हर पोस्ट किया गया है प्रकाशित किया गया था शून्य से एक (?) या एक से अधिक उपयोगकर्ताओं है ।

सामान्य रूप से एक डेटाबेस में, आप होगा को लागू करने के एक बहुत-से-कई संबंध के साथ एक विशेष तालिका: जंक्शन तालिका.

आप का उपयोग नहीं करते जंक्शन तालिका. अपने डेटाबेस सामान्यीकृत नहीं है. हो सकता है आपके वर्तमान समस्या का हल किया जा सकता है को बदलने के बिना डेटाबेस है, लेकिन मैं देख रहा हूँ तो कई समस्याओं को आप हल करने के लिए होगा, शायद नहीं अब, लेकिन निकट भविष्य में: क्या बहुत काम होगा आप की जरूरत है ऐसा करने के लिए यदि आप चाहते हैं को नष्ट करने के लिए एक उपयोगकर्ता हैं? कैसे करते हैं आप "सभी पदों है कि उपयोगकर्ता [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] अद्वितीय है । इस का उपयोग एक प्राथमिक कुंजी

में इकाई की रूपरेखा स्तंभ तालिकाओं के द्वारा प्रतिनिधित्व कर रहे हैं गैर-आभासी गुण है । आभासी गुणों को प्रतिबिंबित संबंधों तालिकाओं के बीच (एक-से-कई, कई-कई)

नोट: एक विदेशी कुंजी है एक असली स्तंभ किसी तालिका में है, इसलिए एक विदेशी कुंजी है, गैर आभासी.

विन्यस्त करने के लिए कई-कई, आप का उपयोग कर सकते हैं धाराप्रवाह एपीआई:

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,
        ...
    }
}

समाधान के बिना सामान्यीकृत डेटाबेस

यदि आप वास्तव में मना नहीं कर सकते हैं, अपनी परियोजना के नेता है कि एक उचित डेटाबेस को रोकने जाएगा का एक बहुत भविष्य में समस्याओं पर विचार करने के लिए बनाने के लिए एक एसक्यूएल पाठ में है कि उचित डाक के लिए आप.

अपने DbContext वर्तमान का प्रतिनिधित्व करता है के कार्यान्वयन के अपने डेटाबेस. यह वर्णित तालिकाओं और संबंधों तालिकाओं के बीच. जोड़ने के लिए एक विधि लाने के पदों के एक उपयोगकर्ता करने के लिए लगता है मुझे एक कानूनी विधि के लिए DbContext.

मेरा एसक्यूएल थोड़ा ज़ंग खाया हुआ है, आप जानते हैं जिस तरह से बेहतर की तुलना में मैं कैसे यह करने के लिए में 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

अपने जवाब के लिए धन्यवाद. हाँ, यह आसान हो जाएगा, तो मैं डेटाबेस सामान्यीकृत, लेकिन यह एक पुरानी प्रणाली है, मैं सिर्फ एक सरल उदाहरण का वर्णन करने के लिए समस्या मैं में मिल गया, परियोजना में इस क्षेत्र से संबंधित करने के लिए चीजों की एक बहुत कुछ, और अधिक समय की जरूरत करने के लिए refactor, जबकि यह मैं बस चाहता हूँ करने के लिए हॉटफिक्स, यह अब है. वैसे भी, अपने जवाब के लिए धन्यवाद.
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ý
..................................................................................................................

इस श्रेणी में लोकप्रिय

लोकप्रिय सवाल इस श्रेणी में