2017-11-02 2 views
0

の多対多リレーションシップから結果リストを取得するには、データベース優先アプローチを使用してEntity Framework many-to-many relationがあります。Entity Framework

私のクラスは次のとおりです。

class User 
{ 
    public int UserId {get; set;} 

    // every User has zero or more Products : 
    public virtual ICollection<Product> Products {get; set;} 

    ... // other properties 
} 

class Product 
{ 
    public int ProductId {get; set;} 

    // every Product belongs to zero or more Users: 
    public virtual ICollection<User> Users {get; set;} 

    ... // other properties 
} 

class MyDbContext : DbContext 
{ 
    public DbSet<User> Users {get; set;} 
    public DbSet<Product> Products {get; set;} 
} 

私はリストlstProductIdsにproductIdsのリストを持っています。 linq

SQLの場合、私はこのようなことをします。

var str = String.Join(",", lstProductIds); 
str = str.Replace(",", "','"); 

var conn = new SqlConnection(cs); 
conn.Open(); 
var cmd = new SqlCommand("SELECT a.UserId,b.ProductId FROM Users a JOIN Product b on a.UserId = b.UserId WHERE ProductId onId IN ('" + str + "')", conn); 
SqlDataReader rdr = cmd.ExecuteReader(); 

while (rdr.Read()) 
{ 
    UserDetails.Add(new UserProduct { OrganizationId = Convert.ToString(rdr["UserId "]), ProductId= Convert.ToString(rdr["ProductId"]) }); 
} 

conn.Close(); 

ユーザーIDとProductIdのリストが表示されます。

私はlinqでも同様のことを試しましたが、これは製品ごとに1つのユーザーIDを与えてしまいます。私が知っているFirstOrDefault()

var UserDetails = db.Products.Where(o => lstProductIds.Contains(o.ProductID.ToString())) 
          .Select(o => new UserProduct 
               { ProductId = o.ID.ToString(), 
               UserId = o.Users.Select(a => a.UserId.ToString()).FirstOrDefault() 
               }) 
          .ToList(); 

は問題であり、それが唯一の製品のために一人のユーザーを選択だが、私はそれは私にすべてのユーザーを取得する方法を変更できますか?

+0

はい、[SelectMany](https://stackoverflow.com/questions/4283866/different-ways-of-using-selectmany) –

答えて

1

、あなたが望む送信された結果を得るためにSelectManyを使用する必要があります。

本のライン上の何か:

UserDetails = db.Products.Where(o => lstProductIds.Contains(o.ProductID.ToString())) 
      .SelectMany(o => o.Users.Select(u => new { o, u })) 
      .Select(s => new UserProduct {ProductId = s.o.ProductId.ToString(), 
       UserId =s.u.UserId.ToString()}).ToList(); 
0

EFで結合を使用できます。このシナリオを理解すると、特定の製品のリスト(lstProductIds)を持つユーザーのすべての製品を取得したいと考えています。コードはテストされていない、あなたはおそらく、内側と外側のキーに対処する必要がありますが、あなたはおそらくのようなものを探している:

db.Users.Join(db.Products.Join(lstProductIds, x => x.ProductId, y => y.ProductId, (x, y) => x), x => x.UserId, y => y.UserId, (x, y) => x).Include(x => x.Products).ToList(); 
+0

に、誰が、なぜ要求する場合私は余分な参加がある、私はそれが行われた言い訳を使用します:P – Tebc

3

これはSelectMany(またはそのLINQに相当)のための仕事です。 @デビッドが指摘するように

例えば

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Linq; 

namespace Ef6Test 
{ 


    class User 
    { 
     public int UserId { get; set; } 

     // every User has zero or more Products : 
     public virtual ICollection<Product> Products { get; } = new HashSet<Product>(); 


} 

    class Product 
    { 
     public int ProductId { get; set; } 

     // every Product belongs to zero or more Users: 
     public virtual ICollection<User> Users { get; } = new HashSet<User>(); 


    } 

    class Db : DbContext 
    { 
     public DbSet<User> Users { get; set; } 
     public DbSet<Product> Products { get; set; } 
    } 




    class Program 
    { 
     static void Main(string[] args) 
     { 

      Database.SetInitializer(new DropCreateDatabaseAlways<Db>()); 

      using (var db = new Db()) 
      { 

       db.Database.Log = m => Console.WriteLine(m); 
       db.Database.Initialize(true); 

       var lstProductIds = new List<int>() { 1, 2, 3 }; 

       var q = from p in db.Products 
         where lstProductIds.Contains(p.ProductId) 
         from u in p.Users 
         select new { p.ProductId, u.UserId }; 

       var UserDetails = q.ToList(); 
      } 

      Console.WriteLine("Hit any key to exit"); 
      Console.ReadKey(); 
     } 
    } 
}