Labas vakaras,
Kāds laiciņš nav nekas šeit rakstīts, jo vasara kā izrādās vienmēr ir viens no karstākajiem periodiem, kad pēkšņi daudzi ir atmodušies no ziemas un pavasara noguruma un sāk plānot darbus un bīdīt lielos plānus, kuri ir jāpabeidz līdz gada beigām, jo nez kāpēc izrādās, ka daudzu programmatūras izstrādes plānu ārējo “jūdžakmens” datumu vadībai parasti nenotrīc roka ielikt datumu, kas sākas ar “01.01.XXXX”. Gadu parasti piedomā klāt pēc tam ;)
Bet ne par to stāsts šoreiz. Raksts tapis saistībā ar nelielu datu bāzes struktūras izmaiņu veikšanu un Entity Framework datu modeļa tālākas piefrizēšanas, par cik datu piekļuve aplikācijā notiek ar EF palīdzību.
Daudzās vietās kodā, ja tas patiešām ir nepieciešams, redzam konstrukciju:
using (var ctx = new Entities())
{
return ctx.Addresses.Include("Client").Select(e => e).ToList();
}
Vienkāršības labad pieņemsim, ka EF modelis mums ir pavisam vienkāršs:

LINQ izteiksme augstāk piemērota situācijās, kad EF konteksts vairs nav pieejams vai arī LazyLoading ir izslēgts, bet vēlāk pēc rezultātu iegūšanas ir nepieciešama kāda informācija no saistošās entītijas – piemēram, šajā gadījumā: meklējam adreses un katrai no adresēm pielādējam klāt arī informāciju par pašu klientu, kam šī adrese pieder, lai vēlāk kādā skatā vai citā vietā izmantotu klienta informāciju.
Kas notiek gadījumos, kad veicam pamatīgu DB refaktoringu un izdomājam, ka beigu beigās “Client” entītiju nesauc vairs par klientu, bet, piemēram, par “Customer” :)
Ok, veicam izmaiņas datu bāzē –> pārsaucam tabulas, visas references un saišu nosaukumus, etc. Pēc tam varam ķerties pie EF modeļa jeb loģiskā aplikācijas slāņa un veikt izmaiņas tur. Pārsaucam entītiju un protams arī visas saites uz citām entītijām.
Daudzas vietas kodā pēc izmaiņām noteikti nekompilēsies, jo, protams, tāds vai šāds tips netiks atrasts. Bet skatoties uz dažādām LINQ izteiksmēm ar .Include(“”) kompilācija norisināsies veiksmīgi, jo viss ir non-typed piegājienā.
Es labprāt pasapņotu par strongly-typed access dažādām metodēm un viena no tām ir ObjectSet<T>.Include(“”). Cik forši būtu, ja varētu uzrakstīt:
return ctx.Addresses.Include(e => e.Client).Select(e => e).ToList();
Vienā momentā apnika refaktorēt un pārdizainēt un nolēmu uzrakstīt paša spēkiem šādu metodi. Un šeit tā arī ir:
public static ObjectQuery<TEntity> Include<TEntity>(this ObjectSet<TEntity> objectSet,
Expression<Func<TEntity, object>> expression)
where TEntity : class
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
var expressionBody = expression.Body;
if (expressionBody.NodeType != ExpressionType.MemberAccess)
{
throw new InvalidOperationException("Expression is not of `MemberAccess' type.");
}
var memberExpression = (MemberExpression)expressionBody;
return objectSet.Include(memberExpression.Member.Name);
}
Metode ir veidota kā paplašinājuma metode ObjectSet<T> objektam, kas nozīmē, ka vienīgā izmaiņa ir pašā Include() metodes argumentā (nu un, protams, arī using pievienošana, ja izmantošana ir citā vārdu telpā nekā paplašinājuma metode).
Protams, šī jaunā metode nepārliecinās, ka tas kas tiek padots argumentā tiešām ir navigācijas property kādai no entītijām un šāda veida izsaukums arī kompilēsies:
return ctx.Addresses.Include(e => e.Client.Name).Select(e => e).ToList();
Kaut gan runtime laikā saņemsim sejā paziņojumu par to, ka paši esam dumji :)

Cerams, ka noderēs!