Well, I am creating a WCF service, that have a large number of classes to communicate with the client, and this classes have also many properties.
Mainly, this classes are the POCO classes that is created with the code generator from the edmx, and I have the .tt file.
To can use this classes and properties, I have to use the DataContract and DataMember, so in each classes I have to set the DataContract and in each property of the each class the DataMemeber. So this a big work, so if I need to do some modify to the data base, I must generate again the tt file and then repeat the work.
Is there any way to do this automatically? I am using .NET 4.0 and EF 4.1.
The whole point of the .tt file being added to your project is so that you can modify the template to suit your needs. All you need to do is change the template so that it adds [DataContract] to the entity class definition and [DataMember] to the entity property definitions.
From there, any time the DB is changed you simple use the "Update model from database" feature and your entities will automatically have their code regenerated using the existing template.
All that said, I'm going to recommend you do not expose your DB entities, POCO or not, directly from your service layer. You should really be designing with domain separation and using messaging and CQRS type patterns at the service level. Then you just have some simple mapping methods that translate the data between those messages/commands to your entities.
There is Entity Framework Provider with WCF data services, might be it can help you.
Related
I am currently developing a Windows service and I am am looking to use MEF to compose all of the services components at run time. The data access module (project) is using Entity Framework 4.1 and a Domain Service Class to perform CRUD operations on the entity model.
The problem I have is how to share the models outside the DAL project when composing the DAL into the worker class in the main project.
For exmaple this is one of the methods in the DAL contract interface
Function GetInspectionFaults() As IQueryable(Of InspectionFault)
This interface is currently in the DAL project (not the shared/referenced project containing the other contract interfaces) as it needs references to the entity model for the POCO types.
How do I shared these POCO types?
Phil
Although it might be a bit more work, you might want to consider having a separate set of models (view models if you will) that you have in a shared assembly (maybe a common/contracts assembly). This would enable your parts to utilise a common set of types which are not explicitly dependent on your DAL.
In regards to separation of concerns, I wouldn't recommend exporting your DAL directly, but provide an abstraction to it via something like the Repository pattern. A repository will handle the communication with the DAL and mapping from your domain to your view models.
You can export and import your repository wherever you need it, which means your parts are not dependent on a specific data source. This makes your code more robust, and more testable.
So I have a layered application that I am adding a WCF service interface on top of. The service is simply a facade with all of our business logic already existing in Business Objects (BOs) within the Business Logic Layer (BLL) which is a class library. Within the BLL we use constructor injection to inject dependencies into the BOs. This is all working with good unit testing, etc. On to the problem...
Ordinarily I'd simply create a set of Request/Response objects as DataContracts for each service method with the appropriate properties for the operation. If the operation required one of our "entities" to be passed either to or from the method, I'd simply define a property of that type and everything would be fine (all of our BOs are serializable). However when one of these "entities" is passed into a service method, WCF deserializes the object without ever invoking the constructors we've defined and, as a result, the dependencies don't resolve.
Let's use the case of a service method called CreateSomething. I'd normally define this as a service operation with a signature like:
CreateSomethingResponse CreateSomething(CreateSomethingRequest request);
CreateSomethingRequest would be a DataContract and have amongst its properties a property of type Something that represented the "entity" being passed into the service. Something, in this case, is a business object that expects to receive an instance of the ISomethingRepository interface from the DI container when instantiated - which, as I said above, does not happen when WCF deserializes the object on the server.
Option #2 is to remove the Something property from the DataContract and define each of the properties explicitly in my DataContract then inside my service method, create a new instance of the Something class, letting the container inject the dependency, then map the property values from the DataContract object into the BO. And I can certainly do that but I am concerned about now having two places to make changes if, say, I want to add a property to the Something type. And, with a lot of properties, there's a lot of code duplication.
Has anyone crossed this bridge and, if so, can you share your thoughts and how you have or would approach this situation in your own applications? Thx!!!
There are two answers on your problem:
First: Do not send your entities and use data transfer objects instead. Your entities are business objects with its logic and data. The logic of business objects is most probably used to control the data. So let the business object control its data in business layer and exchange only dummy crates.
Second: If you don't want to follow the first approach, check documentation of your IoC container. There are ususally two methods for resolving dependencies. For example Unity offers:
Resolve - builds new instance and injects all dependencies (necessary for constructor injection)
BuildUp - takes existing instance and resolves all property dependencies. This should be your choice.
Thanks, Ladislav, for your answer as you confirmed what was already in my head.
What I ended up doing was to change my approach a little. I realized that my use of a business object, per se, was overkill and unnecessary. Or perhaps, just misdirected. When evaluating my requirements, I realized that I could "simplify" my approach and make everything work. By taking each logical layer in my application and looking at what data needed to pass between the layers, I found a design that works.
First, for my business logic layer, instead of a business object, I implemented a Unit of Work object: SomethingManager. SomethingManager is tied to my root Something entity so that any action I want to perform on or with Something is done through the SomethingManager. This includes methods like GetById, GetAll, Save and Delete.
The SomethingManager class accepts two objects in its constructor: an IValidator<Something> and an ISomethingRepository. These will be injected in by the IoC container. The former lets me perform all of the necessary validation using whatever framework we chose (initially the Validation Application Block) and the latter gives me persistance ignorance and abstracts the use of Linq-to-SQL today and makes upgrading to EF4 much easier later on.
For my service layer, I've wired the IoC container (Unity in this case) into WCF so the service instance is created by the container. This allows me to inject an instance of ISomethingManager into my service. Using the interface, I can break the dependency and easily unit test the service class. Plus, because the container is injecting the ISomethingManager instance, it is constructing it and will automatically resolve it's dependencies.
I then created DataContracts to represent how the data should appear when transferred across the wire via the service. Each Request/Response object contains these DataContracts as DataMembers rather than referencing my entity classes (or BOs) directly. It is up to the service method to map the data coming from or going to the Business Logic Layer (via ISomethingManager) - using AutoMapper to make this clean and efficient.
Back in the data layer, I've simply extended the generated entity classes by defining a partial class that implements the desired interface from the BLL. For instance, the Something L2S entity has a partial defined that implements ISomething. And ISomething is what the SomethingManager (and ISomethingManager interface) and ISomethingRepository work with making it very easy to query the database and pass the L2S entity up the chain for the service layer to consume and pass on (without the service layer having any knowledge or dependency on the L2S implementation).
I appreciate any comment, questions, criticisms or suggestions anyone has on this approach.
I read somewhere in stackoverflow itself that when we use POCO classes for WCF contracts using Poco generator , we need not use DataContract and DataMember attributes.WCF do it auto for you? . I don't know how it manages this.
I created a sample application without using these attributes and I was able to generate those entities on client side and use them. I disabled proxy generation and Lazy loading.
Am i missing anything here.? Is there really no need of putting these attributes.
You did it right way. Since WCF 3.5 SP1 it is not needed to add DataContract and DataMember attributes. If attributes are not used all properties with public getter and setter are serialized.
I have a fairly large application, where my data access strategy has always been quite old school:
I have 4 Stored Procedures per Table: TableName_Select, TableName_Insert, TableName_Update, TableName_Delete.
I have a MsSql#DOMAIN#Service class for each logical domain of my application. In that class I have corresponding method to Select, Insert, Update and Delete something in the database.
I want to maintain my own Model classes in a seperate class library project, along with service contracts for WCF services. That enables me to reference only the naked Models, Service Contracts and WCF Service Clients from e.g. a web app or a windows app. (I don't use the auto-generated WCF Service Clients either)
Can I use my own Model classes along with Linq-to-SQL - or do I have to use the autogenerated Models from Linq-to-SQL and then map them over to my own Models in my data access layer before returning them back through the WCF service?
EF Code First FTW!
You don't have to use the auto-generated types with a Linq To Sql data context, but by default the types that you use need to have all the attribute annotations that you'll see on them.
However, Linq to Sql also supports custom mapping (the default being to use the Attributes), where types are mapped to tables and their properties mapped to columns using a MappingSource which is provided to the DataContext on construction.
L2S comes with two - the AttributeMappingSource (used implicitly) and the XMLMappingSource. It's possible with the second of these that you can hand-crank a Linq To Sql DataContext that exposes EntitySets of your own types.
You could even write your own MappingSource - but I think the XML one probably covers most needs.
We have done something similar in our applications. We wrote our own code generator to generate our L2S classes and also what we call our "application" entities. These are much more lightweight than the L2S classes. They are used at the application level to pass data back and forth to our back-end. Each L2S entity class has a built in application entity equivalent where automatic mapping occurs. What I mean is that whenever a L2S entity has data stored to its properties, the values are automatically copied to the respective application entity property. We then have a method on each L2S entity that allows us to retrieve the associated application entity.
So, the short answer is yes, you can use your own classes in conjunction with the L2S entities.
I know there have been similar questions on this topic but I wasn't completely sure they were solving the same problem. So just to be clear...
I have an existing class library that has namespaces for types, business logic and data access. The classes in the logic and data access namespaces are static and have basic crud methods to fill the type instances with data or take type instances that are already full and do inserts or updates in the database.
Now, in addition to the existing applications that reference this library directly, I want to also create a WCF service so that other applications can consume the objects and methods that way.
Every WCF turorial that I see creates the domain objects in the service project - but I don't want my objects defined in two places.
So I was thinking I could reference serialization in my existing class library and mark the type classes as [DataContract] and the properties as [DataMember]. Then, in the WCF project, create the [ServiceContract] interfaces with [OperationContract] methods to match the static logic classes and methods from the existing library that I want to expose. Then, from the WCF project, reference the existing class library and implement the WCF interfaces by having methods in it that call the existing library logic methods which return the existing library types.
Is this a good pattern?
It sounds good but retrofitting serialization tends to be more trouble than it seems at first. I would suggest that you build some lightweight data contracts into a service layer and then build a small tier that sits between your service layer and the business layer to translate the data contracts into business objects and vice-versa.
Assuming your business object can be serialized (have attribute Serializable) one approach could be creating DataContainer object, which will be your data contract. This object would be used in your CRUD methods.
For example your interface could be
Update(DataContainer obj)
Insert(DataContainer obj)
etc.
Then you would use Binary serialization to pack your object into array of bytes and pass it this way through WCF. On the other side you would deserialize them using again BinarySerialization. You just have to make sure that both sides (client and server) have valid version of assembly with your business objects types.