2009-05-18 7 views
1

Wir haben beschlossen, Linq To SQL für unsere Datenschicht in unserem neuesten Projekt zu verwenden. Wir haben eine funktionelle Lösung, die bisher alles gehandhabt hat, was wir mit einem großen Problem angestellt haben. Wir müssen die gleiche Methode immer wieder neu codieren, um nur geringfügig unterschiedliche Ergebnismengen aus unserer Datenbank zu erhalten.Erstellen von Linq nach SQL DRY

Als Beispiel:

 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; 
     } 

Und weiter und weiter bis zum Überdruss.

Gibt es eine Möglichkeit, Linq-Ergebnisse als Parameter an eine Funktion zu übergeben, damit ich meine Objektzuordnungen in einer Funktion platzieren kann und mich nicht so oft wiederhole?

Antwort

2

Ich nahm einen kurzen Stich. Vermutlich kompiliert sie nicht (vor allem das "von teamsTalbe in Teams), aber die Idee ist, dass man etwas ausrechnen kann, das ein IQueryable <> zurückliefert. Du gibst zwar einen anonymen Typ zurück, der aber nicht funktionieren würde muß eine explizite Art zu schaffen, anstelle von ‚wählen Sie neuen {teamsTable, solutionsTable.SolutionName}‘ verwenden

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

Genau das möchte ich tun, aber wie erstelle ich diesen expliziten Typ, wenn nichts von SQL Metal erzeugt wird, um ihn zu finden. –

+0

Erstellen Sie einfach eine Klasse mit öffentlichen Eigenschaften für die zwei Teile, die Sie haben. Wenn Sie das Objekt erstellen, verwenden Sie den Standardkonstruktor mit Eigenschaftsinitialisierungen (nehmen Sie die Eigenschaften nicht als Konstruktorparameter, sonst kann der Ausdruck nicht einem IQueryable zugeordnet werden). –

+0

Ich möchte das in Aktion sehen, kennen Sie irgendwelche Ressourcen oder Tutorials zu dieser Art von Dingen? –

1

Ich denke, Sie könnten Ihre Variable als IEnumerable<YourDataTypeEntity> deklarieren und diese an eine Methode übergeben. Ich neige dazu, es zu tun als Konstrukteur zu mögen:

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

    // ... 
} 
+0

, dass gute Informationen ist und funktioniert, wenn ich aus nur einer einzigen Tabelle am Zug, oder gespeicherte Prozedur. Beachten Sie jedoch, dass ich meine Linq-Anweisungen beitreten lasse, sodass ich den SolutionName-Wert in meinen Objekten bereit habe. Welchen Typ würde ich dafür verwenden? –

+0

Ich habe ein paar einfache Fälle dieses Problems gehabt, und ich habe normalerweise daran gearbeitet, indem ich eine Ansicht in der Datenbank implementierte. –

0

Sie könnten dann eine IQueryable passieren, wenn Sie mit den Ergebnissen beschäftigen möchten dann Sie Itterate über die Ergebnisse. Ich bin mir nicht sicher, ob das etwas ist, was Sie fragen, oder ob ich mit Ihrer Frage weit weg bin.

0

hat auch einen Blick auf AutoMapper, eine API, die einen Konvention basierte Matching-Algorithmus verwendet, um bis Quelle zu Zielwerten in den Objekten. Unter Verwendung dieses würde vermutlich das meiste deines a = bc Codes entfernen.

+0

Danke für den Tipp. Das muss ich bei einem Projekt auf der Straße sagen, danke. –

0

Ich implementierte etwas so mit 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 
      } 

} 

Habe noch nicht so viel getestet, aber es funktioniert. Ich arbeite auch in einer Weise, um zu definieren, welche Eigenschaften basierend auf einem bitflag Parameter geladen werden. Ich dont haben Arbeit noch werden, aber ich mag etwas sein:

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

Erweiterungsmethoden Versuchen: wenn Sie

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

Try Schreiben haben:

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

Auf diese Weise können mehrere schreiben Erweiterungsmethoden, die beliebige IQueryable<Team> abfragen und sie schichten können ...

Um Teams aus der Division 1 mit 9 oder mehr Siege und ein Streifen von 5 oder mehr an einem gewissen Punkt würde man nur schreiben:

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

Wenn Sie nicht wussten, wird Linq die entsprechende SQL-Anweisung basierend auf ALLEN Filtern generieren und eine "finale" Abfrage erstellen, die ausgeführt wird - es wird keine Abfrage für JEDE Funktion ausgelöst. – feemurk