Recommended structure for entity framework for a CRUD DAL for WCF
I need to implement a back-office layer for an application. It will have to implement the data access through EF4, and expose the data access as CRUD through WCF services. The using of WCF Data Service is not an option, because the requirements are to expose a TCP service endpoint.
I see EF in Vs 2010 comes with three code-generator templates for EF:
DbContext
generator, generates the context derived fromDbContext
and the entity classes as very simple POCO's with no extra code;public partial class MyEntities : DbContext {...}
And entity classes
.... public int EmailAddressLocatorID { get; set; } .... public virtual Address Address { get; set; } .... public virtual ICollection<HouseholdGuest> HouseholdGuests { get; set; }
EntityObject
generatorSelf-tracking entity generator, that generates the context derived from
ObjectContext
and entities as POCO classes implementingIObjectWithChangeTracker
andINotifyPropertyChanged,
and helper classObjectChangeTracker
And I found another one on the internet, POCO entity generator, which generates the context based on ObjectGenerator
and the entity classes开发者_Go百科 as POCO with extra code for tracking navigation properties, as below:
public virtual ICollection<Guest> GuestsAddress
{
get
{
if (_guestsAddress == null)
{
var newCollection = new FixupCollection<Guest>();
newCollection.CollectionChanged += FixupGuestsAddress;
_guestsAddress = newCollection;
}
return _guestsAddress;
}
set
{
if (!ReferenceEquals(_guestsAddress, value))
{
var previousValue = _guestsAddress as FixupCollection<Guest>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupGuestsAddress;
}
_guestsAddress = value;
var newValue = value as FixupCollection<Guest>;
if (newValue != null)
{
newValue.CollectionChanged += FixupGuestsAddress;
}
}
}
}
private ICollection<Guest> _guestsAddress;
where FixupCollection is a simple enhancement of ObservableCollection
, implementing ClearItems
and InsertItem,
as below
public class FixupCollection<T> : ObservableCollection<T>
{
protected override void ClearItems()
{
new List<T>(this).ForEach(t => Remove(t));
}
protected override void InsertItem(int index, T item)
{
if (!this.Contains(item))
{
base.InsertItem(index, item);
}
}
}
I would like to ask for advise on which of them would be more appropriate for using to implement the CRUD over a WCF service, and some guidelines on best practices implementing this.
Thanks
- This is probably the best approach from those you mentioned but it will require the biggest effort. First of all you will have to make your entities serializable by WCF = you will have to modify generator to use
DataContract(IsReference = true)
andDataMember
attributes because otherwise you will get cyclic reference exception when serializing object graph (entity with its relations where both principal and dependent have navigation property to each other). Once using object graphs you will also have to make your own change tracking or data merging because you will not know about changes made on client. If you don't plan to transfer object graphs but only single objects or list of the same objects you should be OK with this approach. EntityObject
is specific to Entity Framework and exposing it to clients is a bad idea. It is by default serializable by WCF but it also transfers EF specific information likeEntityKey
. The point of service should be to hide its internal implementation and exposingEntityObject
based entities is violation of that rule. It also doesn't solve change tracking problem.- STEs are designed for the scenario where you want to know about changes in object graphs made on clients but they are not a silver bullet. Services and clients should share only contract describing exchanged messages. STEs violate this rule because they contain logic and client must know and use this logic. STEs are based on sharing entity assembly between service and all clients = clients must be .NET application or the same logic must be reimplemented on non-.NET platform. They also always transfer whole object graph - if you load 100 entities in graph send them back to client and client will make change to single entity in graph it will by default send all 100 entities back to the service.
- POCO generator is generally the same as the first approach. It just uses ObjectContext API instead of DbContext API. Fixup methods are service specific and client will not know about them.
The last approach is using custom non entity classes (DTOs = Data transfer objects) and hide conversion between DTOs and entities in your service. That will allow you to create more complex and suitable set of objects but it will also make your application more complex and increase development complexity. This will be also option in case of implementing your own change tracking.
精彩评论