EF .Include(“..”)

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

 

image

 

 

Cerams, ka noderēs!

Published Wednesday, July 06, 2011 1:43 AM by valdis.iljuconoks

Comments

# re: EF .Include(“..”)

Sveiks!

Labs smadzenu treniņš, līdzīgu tehniku izmantoju DataAnotations kontekstā, kad gribu izgūt piemēram DisplayAttribute lokalizētu vērtību ar custom piegājienu - ne no resursiem.

Gribēju ieteikt izmantot EF4.1, var instalēt, var vienkārši ar NuGet pielikt EntityFramework.dll un tad ieliekam attiecīgo using System.Data.Entity;

un Tevis uzrakstīta funkcionalitāte ir jau pieejama kā Extension metode DbExtensions klasē

Labs vizuāls piemērs atrasts šeit: stackoverflow.com/.../4811557

--atbalsta arī hierahisku Include(), Tevis apskatītajā gadījumā neesmu pārliecināts....

Wednesday, July 06, 2011 11:13 PM by viesis

# re: EF .Include(“..”)

jā, mans risinājums bija pilnīgi no malkas izcirsts. tupoi kak buratjino :D un risināja tikai to problēmu, kas bija jārisina, bet liekas inteliģences.

a par 4.1 - PALDIES! šo biju palaidis garām...

Wednesday, July 06, 2011 11:55 PM by valdis.iljuconoks

Leave a Comment

(obligāts) 
(obligāts) 
(brīvizvēles)
(obligāts)