代码之家  ›  专栏  ›  技术社区  ›  Matthew Vines

使Linq to SQL干燥

  •  1
  • Matthew Vines  · 技术社区  · 15 年前

    我们决定在最近的项目中使用LinqToSQL作为数据层。我们有一个功能性的解决方案,到目前为止,它已经处理了我们抛给它的所有事情,有一个主要问题。我们必须反复编码相同的方法,以便从数据库中检索稍微不同的结果集。

    举个例子:

            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 回复  |  直到 15 年前
        1
  •  2
  •   Frank Schwieterman    15 年前

    我迅速地戳了一下。可能不会编译(尤其是“来自团队中的团队”),但您可以考虑返回iqueryable<>。但是,您的iqueryable返回一个匿名类型,这不起作用。因此,您可能需要创建一个显式类型来代替“select new 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;
        }
    
        2
  •  1
  •   Ben Collins    15 年前

    我想你可以申报 qry 变量AS IEnumerable<YourDataTypeEntity> 把它传递给一个方法。我喜欢作为一个建设者来做:

    class MyDataType
    {
      public MyDataType() {}
      public MyDataType(MyDataTypeEntity mdte)
      {
        // set properties and fields here
      }
    
      // ...
    }
    
        3
  •  0
  •   CSharpAtl    15 年前

    当你想处理结果的时候,你可以发出一个iquerier,然后你对结果进行修正。我不确定这是不是你要问的那种事情,还是我对你的问题有点不知所措。

        4
  •  0
  •   Aleris    15 年前

    也可以看看 AutoMapper ,该API使用基于约定的匹配算法将对象中的源值与目标值进行匹配。使用它可能会删除大部分A=B.C代码。

        5
  •  0
  •   Drevak    15 年前

    我用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
    
        6
  •  0
  •   feemurk    15 年前

    尝试扩展方法: 如果你有

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