WCF, Entity Framework & Data Contracts
Asked Answered
G

3

7

Using VS 2008 & .NET 3.5 SP1:

I am using WCF to allow clients to connect to a service that reads and writes database entries using Entity Framework. By default the entities that are generated automatically from the database have the DataContract attribute applied.

Unfortunately many of the fields are exposed are not meant for consumption by the client (i.e. - records of who is accessing what data, etc.) and for security reasons I would rather keep them from being exposed. Is there any way to avoid Entity Framework classes from being exposed in this manner?

Note: This is not a duplicate of How to prevent private properties in .NET entities from being exposed as public via services?. In that question the user wishes to selectively display certain fields, whereas I would like the entity to not be exposed as a DataContract at all.

Thanks in advance.

Gasconade answered 13/7, 2009 at 20:34 Comment(4)
This may be similar to another posting that was not answered completely: 'wcf and ADO entity framework', https://mcmap.net/q/1476843/-wcf-and-ado-entity-frameworkGasconade
I agree with the answer on the "wcf and ADO entity framework" link you gave. Or you could implement some sort of repository pattern.Cranwell
@Nath - I definitely agree with the answer on the "wcf and ADO entity framework", but unfortunately it does not resolve my problem. The first point in the answer is "Auto generate entity framework entities", which will expose the data that I wish to be kept private as DataContracts. A repository pattern would have the same issue if it were backed by an EF model generated this way as well - unless I am missing something?Gasconade
With the classes you could share to wcf you would only expose items in the model that you want on the wcf side, and when you came to do a .Save(MyEntity) in the repository you could populate your auditing records there.Cranwell
R
13

Are you aware that your entities do not need to map one to one with the database? In particular, you can leave out columns, or even entire tables that are not relevant.

The entity model is meant to be a conceptual model. You can easily create a set of entities for exposure to one set of clients (web services, perhaps), and another set, mapping to the same database, that is meant for a different client (web application, perhaps).

On the other hand, I always recommend against ever exposing Entity Framework objects through a web service. Microsoft unfortunately exposes implementation-dependent properties by marking them with [DataMember]. I just now tried this with a simple service returning a SalesOrderHeader from AdventureWorks. My client received proxy versions of the following EF types:

  • EntityKeyMember
  • StructuralObject
  • EntityObject
  • EntityKey
  • EntityReference
  • RelatedEnd

These are not things your clients need to know about.

I prefer exposing Data Transfer Objects, and copying the properties from one to the other. Obviously, this is better done through reflection or code generation, than by hand. I've done it through code generation in the past (T4 templates).

An option I haven't tried is AutoMapper.

Russell answered 13/7, 2009 at 21:51 Comment(5)
Thanks for your response, John. Yes, I am aware that entities do not need to map one-to-one and can model a subset of the conceptual model, but I don't think that will give me the result I am hoping for. Here is an example: Suppose I have a table of accounts in an accounting system, and I want to audit what operations are being performed on which accounts. I need to expose fields from the account table, but I don't want my potential fraudster to see what information I am tracking about his actions. Continued in next comment...Gasconade
...Continued from previous comment. When the client calls a function I want to create a record and insert it into my audit table for tracking and analysis. I'd like to have both accesible via EF (whether they are in the same or separate entity containers is not important to me). Unfortunately whatever I define as part of the data model gets exposed as a DataContract.Gasconade
So, don't expose that data model. Expose a smaller data model - the one you want exposed. Don't expose the same model to the potential fraudster as you do to the auditing system.Russell
Ahh... The light goes on. ;) The problem isn't with the technology it is with my composition of services -- too monolithic. Thanks, John.Gasconade
+1 Good info. AutoMapper is quite useful for this purpose. I've used it succesfully in a variety of data mapping applications.Longdistance
S
3

We use separate classes for the DataContract objects. We have an interface with one method, ToContract(), and all of our entities implement this interface in a partial class file. It's extra work, and it's boilerplate, but it seems the simplest way to get the separation and granularity of control we need.

Serviceman answered 13/7, 2009 at 21:5 Comment(0)
I
2

I basically see two things you can do:

  1. Either you remove those items you don't want to expose from the DataContract by manually removing the [DataMember] attribute on those items; in that case, WCF will not serialize the properties out
  2. You define your own WCF DataContract classes with just those members you want, and you come up with a logic to convert from your EF entities to your WCF DataContract, using e.g. something like AutoMapper to eliminate (or at least limit) the tedious assigment operations between EF and WCF entities.

Marc

Inharmonic answered 13/7, 2009 at 21:16 Comment(2)
Thanks, marc_s. With respect to point 1 above, how do I manually remove the [DataMember] attribute from those items that are automatically generated from the database? Will this require manual rework each time I update the model from the database?Gasconade
Unfortunately, yes, I'm afraid there's no automatic way to suppress those [DataMember] attributes that I'd be aware of. Therefore the idea of separate WCF classes which you control fully.Inharmonic

© 2022 - 2024 — McMap. All rights reserved.