Создание Linq To SQL DRY - PullRequest
1 голос
/ 18 мая 2009

Мы решили использовать Linq To SQL для нашего уровня данных в нашем последнем проекте. У нас есть функциональное решение, которое до сих пор справлялось со всем, что мы в него бросали, с одной большой проблемой. Мы должны снова и снова кодировать один и тот же метод, чтобы получать только немного разные наборы результатов из нашей базы данных.

Как пример:

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

И то и другое до тошноты.

Есть ли способ передать результаты Linq в качестве параметра функции, чтобы я мог поместить свои сопоставления объектов в одну функцию и не повторять себя так много?

Ответы [ 6 ]

2 голосов
/ 18 мая 2009

Я сделал быстрый удар по нему. Вероятно, не компилируется (особенно "from TeamTalbe в командах"), но идея в том, что вы можете выделить что-то, что возвращает IQueryable <>. Вы, однако, IQueryable, возвращает анонимный тип, который не будет работать. Так что вы можете необходимо создать явный тип для использования вместо 'select new {teamTable, 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;
    }
1 голос
/ 18 мая 2009

Я думаю, вы могли бы объявить вашу переменную qry как IEnumerable<YourDataTypeEntity> и передать ее методу. Мне нравится делать это как конструктор:

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

  // ...
}
0 голосов
/ 19 мая 2009

Попробуйте методы расширения: если у вас есть

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 голосов
/ 18 мая 2009

Я реализовал что-то вроде этого с 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 голосов
/ 18 мая 2009

Также взгляните на AutoMapper , API, который использует алгоритм сопоставления на основе соглашений для сопоставления значений источника и назначения в объектах. Использование этого предположительно приведет к удалению большей части кода a = b.c.

0 голосов
/ 18 мая 2009

Вы можете выдать IQueryable тогда, когда вы захотите разобраться с результатами, тогда вы можете перейти к результатам. Я не уверен, что это то, о чем вы спрашиваете, или я не согласен с вашим вопросом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...