Vergleich Entity Framework Objekte und POCO C# Objekte ...
In meinem letzten Blogeintrag "Einfache C# Objekte (POCO) mit dem Entity Framework lesen ..." habe ich kurz gezeigt, wie man mit dem Entityframework aus einer SQL Server Datenbank einfache Plain Old CLR Objekte mit den Daten lesen/füllen kann. Zu dem Artikel habe ich eine direkte Frage von einem Leser erhalten, wo genau die Unterschiede zwischen einem POCO Objekt und einer Entity Framework generierten Klasse liegen.
Nach kurzen Nachdenken über die berechtigte Frage habe ich folgende Themen im inhaltlichen Umfeld dieser Themen erkannt, und möchte mit diesen und den nächsten Artikeln darüber bloggen. Hier sind die Themen, die in Bezug auf diese Objekte interessant sein könnten:
- Vergleich Entity Framework Objekte und POCO Objekte ...
- Warum sind Entity Framework Objekte und POCO Objekte in einer Architektur wichtig ...
- Datenbankunabhängig Entwurf einer Schichtenarchitektur ...
Heute geht's um den Vergleich --> Wenn man den Code eines POCO Object betrachtet, sieht das zum Beispiel so aus:
public class BeOrder {
public System.Int32 OrderID { get; set; }
public System.String CustomerID { get; set; }
public System.Int32? EmployeeID { get; set; }
public System.DateTime? OrderDate { get; set; }
public System.DateTime? RequiredDate { get; set; }
public System.DateTime? ShippedDate { get; set; }
public System.Int32? ShipVia { get; set; }
public System.Decimal? Freight { get; set; }
public System.String ShipName { get; set; }
public System.String ShipAddress { get; set; }
public System.String ShipCity { get; set; }
public System.String ShipRegion { get; set; }
public System.String ShipPostalCode { get; set; }
public System.String ShipCountry { get; set; }
}
oder im Klassendiagramm:
Die Eigenschaften sind hier dieser extrem einfachen Klasse sind:
-
die Klasse hat keine Basisklasse
die Klasse hat keine fachlichen Methoden
die Klasse hat nur Daten-Properties
die Klasse hat keine Verbindung zum DataContext
die Klasse unterstützt einfaches Databinding.
Im Gegensatz dazu sieht der Code einer Entity Framework Object so aus:
/// <summary>
/// There are no comments for TestDbModel.Orders in the schema.
/// </summary>
/// <KeyProperties>
/// OrderID
/// </KeyProperties>
[global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="TestDbModel", Name="Orders")]
[global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
[global::System.Serializable()]
public partial class Orders : global::System.Data.Objects.DataClasses.EntityObject
{
/// <summary>
/// Create a new Orders object.
/// </summary>
/// <param name="orderID">Initial value of OrderID.</param>
public static Orders CreateOrders(int orderID)
{
Orders orders = new Orders();
orders.OrderID = orderID;
return orders;
}
/// <summary>
/// There are no comments for Property OrderID in the schema.
/// </summary>
[global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
[global::System.Runtime.Serialization.DataMemberAttribute()]
public int OrderID
{
get
{
return this._OrderID;
}
set
{
this.OnOrderIDChanging(value);
this.ReportPropertyChanging("OrderID");
this._OrderID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
this.ReportPropertyChanged("OrderID");
this.OnOrderIDChanged();
}
}
private int _OrderID;
partial void OnOrderIDChanging(int value);
partial void OnOrderIDChanged();
/// <summary>
/// There are no comments for Property EmployeeID in the schema.
/// </summary>
[global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()]
[global::System.Runtime.Serialization.DataMemberAttribute()]
public global::System.Nullable<int> EmployeeID
{
get
{
return this._EmployeeID;
}
set
{
this.OnEmployeeIDChanging(value);
this.ReportPropertyChanging("EmployeeID");
this._EmployeeID = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
this.ReportPropertyChanged("EmployeeID");
this.OnEmployeeIDChanged();
}
}
Die Vererbungshierarchie dieses Entity Framework generierten Object sieht so aus:
Die Klasse hat die Basisklasse EntityObject definiert im System.Data.Objects.DataClasses Namespace. Die EntityObjects Klasse hat wiederrum das Klasse StructuralObject ebenfalls definiert in System.Objects.DataClasses als Basisklasse. Die Klasse Orders selbst hat folgendes Diagramm:
Die Eigenschaften der Entityframework Klasse sind folgende:
-
die Klasse hat Basisklassen
die Klasse hat keine fachlichen Methoden
die Klasse hat nur Daten-Properties
die Klasse kann direkt an den DataContext gekoppelt werden (via context.Attach/Detach)
die Klasse unterstützt komplexes Databinding.
Der Vergleich der Codemetric zeigt, dass ein Entity Framework Object etwas komplexer als ein typisches POCO ist.
Der Vergleich im Profiler zeigt, das Entity Framework Objekte etwas mehr Speicher als unser Beispiel POCO brauchen (- man kann das aus den Inclusive Bytes / Inclusive Allocations errechnen).
Wenn ich ein Object in einem Usecase aus der Datenbank lesen und in der Anwendung benutzen und danach dasselbe Object wieder in die Datenbank speichern möchte, ist das Entity Frameobject empfehlenswert. Da es dieses Szenario sehr effizient durch ein Entity Framework Object unterstützt wird.
Abstracter Beispielcode eines solchen Szenarios:
EntityKey key;
object originalItem;
TestDbEntities nwindDbCtx = new TestDbEntities();
// Data layer - get the customer from DB and detach from DB
Customers customer = (from c in nwindDbCtx.Customers
where c.CustomerID == "ALFKI"
select c).First();
nwindDbCtx.Detach( customer );
// .....
// .....
// UI layer - modify the entity on screen - assign the entity to an UI element and modify it
modifyForm.DataContext = customer;
// ..... // ..... .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
// Data layer - attach the entity back and save the changes
key = nwindDbCtx.CreateEntityKey( "Customers", customer );
if ( nwindDbCtx.TryGetObjectByKey( key, out originalItem ) )
{
nwindDbCtx.ApplyPropertyChanges( key.EntitySetName, customer );
}
nwindDbCtx.SaveChanges();
Anmerkung zum Code: Dadurch, dass die Entityframework Klasse "two-way" Data binding unterstützt, ist eine Rücksyncronsation aus den Eingabefeldern der UI Form nicht notwendig, dass geschieht automatisch.
Wenn man allerdings ein anderes Anwendungszenario hat, bei dem zum Beispiel Daten über eine Serviceschnittstelle ausgetauscht werden, können die einfachen POCO Objekte vorteilhaft sein.
Damit kann man zusammenfassen, dass der Entwurf eines Entity Framework Object ein wenig komplexer als ein generisches CLR Object ist. Allerdings sind die zusätzlichen Methoden für Datenzuweisungen und Databinding-Funktionen optimiert.
Das Entity Framework unterstützt die Zusammenarbeit mit beiden Objekttypen.
Comments
- Anonymous
September 09, 2008
PingBack from http://housesfunnywallpaper.cn/?p=5011