Creating Linq To SQL DRY
We decided to use Linq To SQL for our data layer in our last project. We have a functional solution that has handled everything we've thrown at it so far, with one major issue. We have to reintroduce the same method over and over to retrieve only slightly different result sets from our database.
As an example:
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;
}
And on and on the announcement of ads.
Is there a way to pass the Linq results as a parameter to a function, so I can put my object mappings in one function and not iterate myself so much?
a source to share
I hit him quickly. It probably doesn't compile (especially "from Talbe commands in commands"), but the idea is that you can deduct something that returns an IQueryable <>. You IQueryable return an anonymous type, although that won't work. you must create an explicit type to use instead of "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;
}
a source to share
Also have a look at AutoMapper , an API that uses a convention-based matching algorithm to map source values to target values into objects. Using this will probably remove most of your a = bc code
a source to share
I have implemented something like this using 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
}
}
Haven't tested this yet, but it works. I also work this way to determine which properties to load based on the bitflag parameter. I don't have a job yet, but will be something like:
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
a source to share
Try extension methods: if you have
public IQueryable<Team> GetTeams() { return db.Teams; }
Try to write:
public IQueryable<Team> WithDivisionId(this IQueryable<Team> qry, int divisionId)
{ return (from t in qry where t.DivisionId = divisionId select t);}
This way you can write multiple extension methods that can query any IQueryable<Team>
and overlay them on ...
To get teams from division 1 with 9 or more wins and a streak of 5 or more at some point, you would simply write:
GetTeams().WithDivisionId(1).HavingWonAtLeast(9).WithWinningStreak(5);
a source to share