Archive for the ‘Entity Framework’ Category

Entity Framework 4 többrétegű appokban

Tuesday, April 20th, 2010

Játszottam kicsit az EF4-gyel. Az alábbi kód egy n rétegű app adatmozgását szimulálja a WCF xml szerializálóját használva. Mindhárom template-tel kipróbáltam, alább láthatóak az adatmozgások.
A tesztkód messze nem korrekt, de kiindulópontként további vizsgálatokhoz elfogatható:


using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;

namespace POCO1
{
    class Program
    {
        static void Main()
        {
            Department d;
            using (var e = new SchoolEntities())
            {
                e.ContextOptions.ProxyCreationEnabled = false;
                e.ContextOptions.LazyLoadingEnabled = false;
                d = e.Departments.Include("Courses").Single(dep => dep.DepartmentID == 1);
                Console.WriteLine("{0}", d.Name);
                Console.WriteLine("---------------------");
                foreach (Course c in d.Courses)
                {
                    Console.WriteLine("{0}", c.Title);
                }
                e.Detach(d);
            }

            var ser = new DataContractSerializer(d.GetType());
            //var ser = new DataContractSerializer(d.GetType(),
            //null, 50000, true, true, null, new ProxyDataContractResolver());

            using (var s2c = new FileStream(@"c:\temp\Server2Client.xml", FileMode.Create, FileAccess.ReadWrite))
            {
                //1. Server küld kliensre
                ser.WriteObject(s2c, d);
                s2c.Position = 0;
                //2. Kliens deserializál
                var clientSideDep = (Department)ser.ReadObject(s2c);

                //Csak ST
                //bool ce = clientSideDep.ChangeTracker.ChangeTrackingEnabled;

                //3. Kliens módosít
                clientSideDep.Name += "a";

                using (var c2s = new FileStream(@"c:\temp\Client2Server.xml", FileMode.Create, FileAccess.ReadWrite))
                {
                    //4. Kliens visszaküld
                    ser.WriteObject(c2s, clientSideDep);
                    c2s.Position = 0;

                    //5.Server deserializál
                    var sentBackDepartment = (Department)ser.ReadObject(c2s);
                    using (var e = new SchoolEntities())
                    {
                        //6. Server visszamódosít

                        //Normál entitás
                        e.Departments.Attach(sentBackDepartment);
                        e.ObjectStateManager.GetObjectStateEntry(sentBackDepartment).SetModified();
                        e.ObjectStateManager.GetObjectStateEntry(sentBackDepartment).SetModifiedProperty("Name");

                        //POCO
                        //e.Departments.Include("Courses").Single(dep => dep.DepartmentID == 1);
                        //e.Departments.ApplyCurrentValues(sentBackDepartment);

                        //Self-tracking entity
                        //e.Departments.ApplyChanges(sentBackDepartment);

                        e.SaveChanges();
                    }
                }
            }
        }
    }
}

EF alapobjektumok szerviz => kliens:


<Department z:Id="i1" xmlns="http://schemas.datacontract.org/2004/07/POCO1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
  <EntityKey z:Id="i2" xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:a="http://schemas.datacontract.org/2004/07/System.Data">
    <a:EntityContainerName>SchoolEntities</a:EntityContainerName>
    <a:EntityKeyValues>
      <a:EntityKeyMember>
        <a:Key>DepartmentID</a:Key>
        <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Value>
      </a:EntityKeyMember>
    </a:EntityKeyValues>
    <a:EntitySetName>Departments</a:EntitySetName>
  </EntityKey>
  <Administrator>2</Administrator>
  <Budget>350000.0000</Budget>
  <Courses/>
  <DepartmentID>1</DepartmentID>
  <Name>Engineering</Name>
  <StartDate>2007-09-01T00:00:00</StartDate>
</Department>

EF alapobjektumok kliens => szerviz:


<Department z:Id="i1" xmlns="http://schemas.datacontract.org/2004/07/POCO1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
  <EntityKey z:Id="i2" xmlns="http://schemas.datacontract.org/2004/07/System.Data.Objects.DataClasses" xmlns:a="http://schemas.datacontract.org/2004/07/System.Data">
    <a:EntityContainerName>SchoolEntities</a:EntityContainerName>
    <a:EntityKeyValues>
      <a:EntityKeyMember>
        <a:Key>DepartmentID</a:Key>
        <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Value>
      </a:EntityKeyMember>
    </a:EntityKeyValues>
    <a:EntitySetName>Departments</a:EntitySetName>
  </EntityKey>
  <Administrator>2</Administrator>
  <Budget>350000.0000</Budget>
  <Courses/>
  <DepartmentID>1</DepartmentID>
  <Name>Engineeringa</Name>
  <StartDate>2007-09-01T00:00:00</StartDate>
</Department>

POCO szerviz => kliens:


<Department xmlns="http://schemas.datacontract.org/2004/07/POCO1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Administrator>2</Administrator>
  <Budget>350000.0000</Budget>
  <Courses/>
  <DepartmentID>1</DepartmentID>
  <Name>Engineeringa</Name>
  <StartDate>2007-09-01T00:00:00</StartDate>
</Department>

POCO kliens => szerviz:


<Department xmlns="http://schemas.datacontract.org/2004/07/POCO1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Administrator>2</Administrator>
  <Budget>350000.0000</Budget>
  <Courses/>
  <DepartmentID>1</DepartmentID>
  <Name>Engineeringaa</Name>
  <StartDate>2007-09-01T00:00:00</StartDate>
</Department>

Self-tracking entity, szerviz => kliens:


<Department z:Id="i1" xmlns="http://schemas.datacontract.org/2004/07/POCO1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
  <Administrator>2</Administrator>
  <Budget>350000.0000</Budget>
  <ChangeTracker z:Id="i2">
    <ExtendedProperties/>
    <ObjectsAddedToCollectionProperties/>
    <ObjectsRemovedFromCollectionProperties/>
    <OriginalValues/>
    <State>Unchanged</State>
  </ChangeTracker>
  <Courses/>
  <DepartmentID>1</DepartmentID>
  <Name>Engineeringaaaaaaaa</Name>
  <StartDate>2007-09-01T00:00:00</StartDate>
</Department>

Self-tracking entity, kliens => szerviz:


<Department z:Id="i1" xmlns="http://schemas.datacontract.org/2004/07/POCO1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
  <Administrator>2</Administrator>
  <Budget>350000.0000</Budget>
  <ChangeTracker z:Id="i2">
    <ExtendedProperties/>
    <ObjectsAddedToCollectionProperties/>
    <ObjectsRemovedFromCollectionProperties/>
    <OriginalValues/>
    <State>Modified</State>
  </ChangeTracker>
  <Courses/>
  <DepartmentID>1</DepartmentID>
  <Name>Engineeringaaaaaaaaa</Name>
  <StartDate>2007-09-01T00:00:00</StartDate>
</Department>

Érdekes, hogy a módosítás ténye csak a ST-ben látszik, még az eredeti entity-sben sem. A POCO-tól nem is vártuk persze.
Később még majd foglalkozok bővebben a témával. Aki játszani akar vele, hozza létre a School EF példaadatbázist, azon lehet futtatni.

EF SSDL alapú felhasználói bemenet ellenőrzés

Monday, February 1st, 2010

A következőn töröm a fejem. Az Entity Framework SSDL-jében definiálva vannak az entitás property-k alapvető jellemzői: nullázhatóság, max hossz. Ezeket a GUI-n ki kell kényszeríteni. Nyilván vannak összetettebb validálási szabályok, de most koncentráljunk ezekre az elemiekre.
Utálok minden redundanciát egy rendszerben, ezért azt gondoltam, a szabályokat kiolvasom az EF sémájából, és ebből táplálom meg a validáló részeket, így nem kell törődni az egyszerű validálásokkal, automatikusan működni fognak.

A következő kis kódocska mutatja meg a metaadatok használatát:


o.ForceLoadingSchemas();

var sspaceEntitySets = o.MetadataWorkspace
       .GetItems<EntityContainer>(DataSpace.SSpace)
       .First().BaseEntitySets.OfType<EntitySet>();

foreach (EntitySet es in sspaceEntitySets)
{
    foreach (EdmProperty p in es.ElementType.Properties)
    {
        ReadOnlyMetadataCollection<Facet> facets = p.TypeUsage.Facets;
        Debug.WriteLine("{0} is {1} nullable", p.Name, (bool)facets["Nullable"].Value ? "" : "not");
        if (facets.Contains("MaxLength"))
        {
            Debug.WriteLine("{0} MaxLenght is {1}", p.Name, (int)facets["MaxLength"].Value);
        }
        Debug.WriteLine("{0} is {1} nullable", p.Name, (bool)facets["Nullable"].Value ? "" : "not");
    }
}

A ForceLoadingSchemas az ObjectContext partial classában van:


public void ForceLoadingSchemas()
{
    CreateQuery<BusinessEntity>("AdventureWorks2008Entities3.BusinessEntities").ToTraceString();
}

Csinált már valaki ilyet? Van benne valami csapda, amit most nem látok?

Jó Entity Framework architektúra cikkek

Tuesday, January 19th, 2010

Hogyan építsünk EF-re többrétegű appot?
1. Anti-Patterns To Avoid In N-Tier Applications
2. N-Tier Application Patterns
3. Building N-Tier Apps with EF4

Jó cikkek.