2015-05-07 55 views
3

分組,我有以下表LEFT JOIN通過linq2db

class Directory 
{ 
    public long Id { get; set;} 
    public string Path { get; set;} 
    public IEnumerable<File> Files { get; set;} 
} 

class File 
{ 
    public long Id { get; set;} 
    public long DirectoryId { get; set; } 
    public string Name { get; set; } 
    public Directory Directory { get; set; } 
} 

我怎樣才能用合適的文件ID分組目錄使用留在一個查詢中加入和linq2db?

我想應該是這樣的

var query = from d in db.Direcories 
      join f in db.Files on d.Id equals f.DirectoryId into items 
      from i in items.DefaultIfEmpty() 
      group i by new { d } into g 
      select new { Directory = g.Key, Files = ????? }; 

var result = query.ToList(); 

,但我不知道如何從組

+0

linq2db https://github.com/linq2db/linq2db – Ten

+0

謝謝,我更新了標籤維基。我以前從來沒有聽說過。 – jessehouwing

回答

1

首先,我強烈建議使用T4模板生成您的數據模型類,所以看看這個項目:linq2db/t4models。我也推薦看這裏的視頻:https://github.com/linq2db/linq2db/wiki

具有T4生成我的數據模型後,它會是這個樣子:

public partial class TestDb : LinqToDB.Data.DataConnection 
{ 
    public ITable<Directory> Directories { get { return this.GetTable<Directory>(); } } 
    public ITable<File>   Files   { get { return this.GetTable<File>(); } } 
} 

[Table(Schema="dbo", Name="Directory")] 
public partial class Directory 
{ 
    [PrimaryKey, Identity] public int ID { get; set; } // int 
    [Column,  NotNull ] public string Path { get; set; } // varchar(max) 

    #region Associations 

    /// <summary> 
    /// FK_File_Directory_BackReference 
    /// </summary> 
    [Association(ThisKey="ID", OtherKey="DirectoryID", CanBeNull=true, IsBackReference=true)] 
    public List<File> Files { get; set; } 

    #endregion 
} 

[Table(Schema="dbo", Name="File")] 
public partial class File 
{ 
    [PrimaryKey, Identity] public int ID   { get; set; } // int 
    [Column,  NotNull ] public int DirectoryID { get; set; } // int 
    [Column,  NotNull ] public string Name  { get; set; } // varchar(max) 

    #region Associations 

    /// <summary> 
    /// FK_File_Directory 
    /// </summary> 
    [Association(ThisKey="DirectoryID", OtherKey="ID", CanBeNull=false, KeyName="FK_File_Directory", BackReferenceName="Files")] 
    public Directory Directory { get; set; } 

    #endregion 
} 

現在有幾種方式來加載目錄及其文件。這裏有幾個:

[Test] // 1 query to load directories + separate queries to load files for each directory 
public void Test() 
{ 
    LinqToDB.Common.Configuration.Linq.AllowMultipleQuery = true; 
    using(var db = new TestDb()) 
    { 
     var directoriesWithFiles = db.Directories.LoadWith(d => d.Files).ToList(); 
    } 
} 

[Test] // same as above, but manually 
public void Test2() 
{ 
    using(var db = new TestDb()) 
    { 
     var directories = db.Directories.ToList(); 

     foreach (var d in directories) 
     { 
      d.Files = db.Files.Where(f => f.DirectoryID == d.ID).ToList(); 
     } 
    } 
} 

[Test] // if you want only 2 queries to the database 
public void Test3() 
{ 
    using (var db = new TestDb()) 
    { 
     var dict = new Dictionary<int, List<File>>(); 

     foreach(var file in db.Files) 
     { 
      if(!dict.ContainsKey(file.DirectoryID)) 
       dict.Add(file.DirectoryID, new List<File> { file }); 
      else 
       dict[file.DirectoryID].Add(file); 
     } 

     var directories = db.Directories.ToList(); 

     foreach (var d in directories) 
     { 
      List<File> files; 
      d.Files = dict.TryGetValue(d.ID, out files) ? files : new List<File>(); 
     } 
    } 
} 

或者你可以做一個連接,在1個查詢負載的一切,然後在內存中的文件手動連接到目錄。你可以編寫自己的擴展方法來簡化它。

0

對LINQ聯接語法是相當困難得到文件繞到那些頭..我一般適用小動作只使用您作爲中間結果創造了「項目」變量:

var query = from d in db.Direcories 
     join f in db.Files on d.Id equals f.DirectoryId into items 
     from f in items.DefaultIfEmpty() 
     group f by d into g 
     select new { Directory = g.Key, Files = g /* optionally add .ToList() or .ToEnumerable() */ }; 

var result = query.ToList(); 

雖然我懷疑有更容易的方式來完成你」如果您定義了正確的關係屬性,請嘗試使用db.Directories.Include(d => d.Files)或類似的構造。

0

對此一試:

var query = from fileAndFolder in 
       (
        from d in db.Directories 
        from f in db.Files.Where(ff => ff.DirectoryId == d.Id).DefaultIfEmpty() 
        select new { d, f } 
       ) 
      group fileAndFolder by fileAndFolder.d into g 
      select new { DirectoryId = g.Key, Files = g };