2009-05-18 124 views
1

我們決定在最近的項目中使用Linq To SQL作爲我們的數據層。我們有一個功能性的解決方案,迄今爲止我們已經處理了所有的問題,並帶來了一個主要問題。我們必須一遍又一遍地編寫相同的方法來從數據庫中檢索稍微不同的結果集。將Linq轉換爲SQL DRY

舉個例子:

 public List<TeamBE> GetTeamsBySolutionID(Guid SolutionID) 
     { 
      List<TeamBE> teams = new List<TeamBE>(); 

      Esadmin db = new Esadmin(_connectionString); 

      var qry = (from teamsTable in db.Teams 
         join solutionsTable in db.Solutions on teamsTable.SolutionID equals solutionsTable.SolutionID 
         where teamsTable.SolutionID == SolutionID 
         select new { teamsTable, solutionsTable.SolutionName }); 

      foreach (var result in qry) 
      { 
       TeamBE team = new TeamBE(); 

       team.TeamID = result.teamsTable.TeamID; 
       team.Description = result.teamsTable.Description; 
       team.Status = result.teamsTable.Status; 
       team.LastModified = result.teamsTable.LastModified; 
       team.SolutionID = result.teamsTable.SolutionID; 
       team.SolutionName = result.SolutionName; 
       team.Name = result.teamsTable.Name; 
       team.LocationLevel = result.teamsTable.LocationLevel; 
       team.AORDriven = result.teamsTable.AoRDriven; 
       team.CriteriaID = result.teamsTable.CriteriaID ?? Guid.Empty; 

       teams.Add(team); 
      } 
      return teams; 
     } 

     public TeamBE GetTeamByID(Guid TeamID) 
     { 
      Esadmin db = new Esadmin(_connectionString); 
      TeamBE team = new TeamBE(); 

      var qry = (from teamsTable in db.Teams 
         join solutionsTable in db.Solutions on teamsTable.SolutionID equals solutionsTable.SolutionID 
         where teamsTable.TeamID == TeamID 
         select new { teamsTable, solutionsTable.SolutionName }).Single(); 

      team.TeamID = qry.teamsTable.TeamID; 
      team.Description = qry.teamsTable.Description; 
      team.Status = qry.teamsTable.Status; 
      team.LastModified = qry.teamsTable.LastModified; 
      team.SolutionID = qry.teamsTable.SolutionID; 
      team.SolutionName = qry.SolutionName; 
      team.Name = qry.teamsTable.Name; 
      team.LocationLevel = qry.teamsTable.LocationLevel; 
      team.AORDriven = qry.teamsTable.AoRDriven; 
      team.CriteriaID = qry.teamsTable.CriteriaID ?? Guid.Empty; 

      return team; 
     } 

和和廣告nauseum。

有沒有辦法將Linq結果作爲參數傳遞給一個函數,所以我可以將我的對象映射放在一個函數中,而不是重複自己這麼多?

回答

2

我快速地刺了一下。可能不會編譯(尤其是「從teamTalbe組隊」),但是這個想法是你可以將返回IQueryable的東西排除在外。你是IQueryable返回一個匿名類型,但這不起作用。需要建立一個明確的類型來代替使用「選擇新{teamsTable,solutionsTable.SolutionName}」

public List<TeamBE> GetTeamsBySolutionID(int solutionID) 
    { 
     Esadmin db = new Esadmin(_connectionString); 
     return GetTeamsBy(db, _GetTeamsBySolutionID(db, solutionID)); 
    } 

    IQueryable<Team> _GetTeamsBySolutionID(Esadmin db, int solutionID) 
    { 
     return from teamsTable in db.Teams 
       where teamsTable.SolutionID == SolutionID 
       select teamsTable; 
    } 

    List<TeamBE> GetTeamsBy(Esadmin db, IQueryable<Team> teams) 
    { 
     List<TeamBE> teams = new List<TeamBE>(); 

     var qry = (from teamsTable in teams 
        join solutionsTable in db.Solutions on teamsTable.SolutionID equals solutionsTable.SolutionID 
        select new { teamsTable, solutionsTable.SolutionName }); 

     foreach (var result in qry) 
     { 
      TeamBE team = new TeamBE(); 

      team.TeamID = result.teamsTable.TeamID; 
      team.Description = result.teamsTable.Description; 
      team.Status = result.teamsTable.Status; 
      team.LastModified = result.teamsTable.LastModified; 
      team.SolutionID = result.teamsTable.SolutionID; 
      team.SolutionName = result.SolutionName; 
      team.Name = result.teamsTable.Name; 
      team.LocationLevel = result.teamsTable.LocationLevel; 
      team.AORDriven = result.teamsTable.AoRDriven; 
      team.CriteriaID = result.teamsTable.CriteriaID ?? Guid.Empty; 

      teams.Add(team); 
     } 
     return teams; 
    } 
+0

這正是我期待做的,但是如何在SQL金屬沒有產生與之相匹配的情況下創建顯式類型。 – 2009-05-18 17:58:33

+0

只需爲您擁有的兩個部分創建一個具有公共屬性的類。當你創建對象時,使用帶有屬性初始值設定項的默認構造函數(不要把這些屬性作爲構造函數參數,否則表達式不能映射到IQueryable) – 2009-05-18 18:03:52

+0

我希望看到這個動作,你知道任何資源或教程在這種事情? – 2009-05-18 18:09:04

1

我想你可以聲明你的qry變量爲IEnumerable<YourDataTypeEntity>並將其傳遞給一個方法。我傾向於喜歡做它作爲一個構造函數:

class MyDataType 
{ 
    public MyDataType() {} 
    public MyDataType(MyDataTypeEntity mdte) 
    { 
    // set properties and fields here 
    } 

    // ... 
} 
+0

這是很好的信息,當我從只是一個單一的表拉動將工作,或存儲過程。但請注意,我在我的linq語句中執行了一個連接,因此我已經準備好了SolutionName的值以進入我的對象。我會用什麼類型的。 – 2009-05-18 17:53:01

+0

我有幾個簡單的例子,我通常通過在數據庫中實現一個視圖來解決它。 – 2009-05-18 18:19:17

0

你可以傳遞出一個IQueryable然後當你要處理的結果,那麼你Itterate過的結果。我不確定這是你問的問題還是我的問題。

0

也看看AutoMapper,使用基於約定匹配算法來匹配源的API到目標值的對象。使用這可能會刪除大多數你的a = bc代碼。

+0

感謝您的提示。我將不得不在這個項目上投下一筆,謝謝。 – 2009-05-18 18:11:06

0

我用entityFramework實現了這樣的東西:

//This returns an IQueryable of your Linq2Sql entities, here you put your query. 
protected IQueryable<Team> GetTeamByIdQuery(Guid teamID) 
{ 
    var qry = (from TeamsTable in db.Teams 
       where blablabla..... 
       select Teams; 

    return qry; 
} 


//This will return your real entity 
public IList<TeamBE> GetTeamById(Guid teamID) 
{ 
    var query = this.GetTeamByIdQuery(teamID); 
    IList<TeamBE> teams = ExecuteTeamQuery(query).toList<TeamBE>(); 

    return teams; 
} 


//this method will do the mapping from your L2S entities to your model entities 
protected IQueryable<TeamBE> ExcuteTeamQuery(IQueryable<Team> query) 
{ 
    return 
     query.select<Team, TeamBE> (team => 
      new TeamBE 
      { 
       TeamID = team.TeamID, 
       Description = team.Description 
      } 

} 

還沒有測試,但它的工作原理。我也在根據bitflag參數定義要加載哪些屬性。我沒有它的工作還沒有,但會是這樣的:

public IQueryable<TeamBE> ExcuteTeamQuery(IQueryable<Team> query, int loadLevel) 
{ 
    return 
     query.select<Team, TeamBE> (team => 
      new TeamBE 
      { 
       TeamID = team.TeamID, 
       TeamMembers = (HaveToLoad(LoadLevel.TeamMembers, loadLevel)) ? team.TeamMembers : null 
      } 

} 


enter code here 
0

嘗試擴展方法: 如果你有

public IQueryable<Team> GetTeams() { return db.Teams; } 

嘗試寫:

public IQueryable<Team> WithDivisionId(this IQueryable<Team> qry, int divisionId) 
{ return (from t in qry where t.DivisionId = divisionId select t);} 

這樣你就可以寫多擴展方法,可以查詢任何IQueryable<Team>並將它們分層...

要想從部門1隊有9次或更多的勝利,並在某些時候的5以上的連勝,你會這樣寫:

GetTeams().WithDivisionId(1).HavingWonAtLeast(9).WithWinningStreak(5); 
+0

如果您不知道,Linq會根據所有過濾器生成適當的SQL語句,並創建一個將執行的「最終」查詢 - 它不會爲每個函數啓動查詢。 – feemurk 2009-05-18 22:17:14