WPF WCF Prism and MVVM - correct way to expose entities
Asked Answered
L

2

7

We are going to be developing a large enterprise desktop application very soon and i have been spending some time researching the WPF + PRISM + MVVM approach, i have got a good grasp on most of the concepts and am loving the modularity it provides.

Where i am having problems is with how to architect the services layer to get data in and out, especially when this service is introduced by a module with the idea that dependant module can use it.

I wanted to abstract my WCF data services inside of application services and use ServiceLocator to resolve concrete instances from within my view-models, however im having a hard time working out how this should hang together, mainly due to my entites being part of the WCF service.

For example

Module1 Contains WCF Service + Concrete Application Service(ISearchService) + WCF Service generated entities(model)

Module1.Infastructure - Contains the following interface for the application service

public interface ISearchService
{
      ObservableCollection<Person> Search(string search);
}

this would be registered in the UnityContainer so that any other module can get the concrete implementation introcuded by the module.

My problem is that the Entities (Person) are defined in the module itself (in the WCF service), so introducing a service and then expecting any other modules to be able to use it means they need to reference the module itself not just the modules infastructure, unless i pull out the services into another assembly.

Should i be exposing my entites that are auto generated from my EF model in this way?

Does anyone have a better solution ?

Laudianism answered 3/4, 2012 at 12:52 Comment(2)
You might be interested in this question of mine about if the WCF service should return the Model objects, or a data transfer object. I ended up going with a DTO, and found it much easier to have it return a data transfer object and use something like AutoMapper to map DTOs to Models and vice versaMirabella
I like that idea, would using POCO's in Entity Framework basically be the same thing?Laudianism
Q
1

Here is how did it.

I'm currently using Silverlight + PRISM + MVVM + WCF (RIA) services.

With the current project architecture

  • Application.Domain : Containing all the EF code first entities including metadata and business validation. Does not include database generation.
  • Application.RIAServices : This is the project that contains the auto generated classes from WCF RIA services web project. I can reference this project in both WPF and Silverlight.

  • Application.RIAServices.Web : Webproject containing the DomainServices and database generation code by using the DbContext. this is the WCF RIA link project for Application.RIAServices

  • Application.Infrastructure : This is where it starts. Because just like you I have a Person/Customer Service using an interface ICustomerService. Because I want to use this service for example application wide and not only in the ModuleA, I place this interface in the Infrastructure. All projects contain a reference to this project.

  • Application.Modules.ModuleA --> Application.Modules.ModuleD : General modules providing functionality. All of my modules (that use WCF RIA Services) have a reference to the Application.Infrastructure and Application.RIAServices projects.

  • Application.Shell : Startup project. having the bootstrapper and registering all relevant modules.

Reading Rachels question made me think about certain things and I just wanted to leave my structure on how I did it. You might have an idea about it. I Don't want to go to DTO yet because things like validation are so good intregrated in WCF RIA services that it automaticly reflects in the textbox when something is wrong and displaying an error message. Looking forward to hearing your opinion and the outcome of the question/issue

Edit:

Application.Domain also has a separate structure aswell.

I have my Models. Only container pure properties that need to be mapped to the database. Then I have my Metadata folder. Now for this to work I need to have the same namespace as my Entity and I make the entity partial. I create a Entity.metadata.cs file and in there I create a internal sealed class EntityMetaData, Copying the properties and adding attributes to it them. By using the MetadataType attribute above the Entity class it adds all those attribute to the EF/WCF RIA code generator.

One of those attribute is the CustomValidation it use a static class and a method paramater and validates the entity on the server. Or if you create the file with a .shared.cs extension it gets generated to the Application.RIAServices project.

Possibility

To try to answer your question, you might have only 1 option and that is what you suggested at first. You can create a Customer.Infrastructure Project.

this project contains the interface for the ICustomerService, the Entity/DTO/POCO what ever you want, and maybe even a implementation of this ICustomerService or the WCF service. This then allows all your modules to reference this project and thus not creating dependecies between modules.

Quadrennial answered 4/4, 2012 at 9:30 Comment(5)
every resource i have found states that RIA services is not supported in WPF, is this not the case?Laudianism
I want to restrict my services so they only deal with entities that are relevant to the module, even though they may or may not share the same database, my problem is i end up with my EF POCOS - my generated service entities which i dont really want to expose, then maybe another DTO - its just a mess with each entity represented umpteen times..Laudianism
@RichardFriend I need to look at that. I can reference the project create a reference and create a customercontext. But I have 't seen it at runtime. I will have a look. Regarding your issue there might be a way to restrict the container to resolving instance. Also will have a lookQuadrennial
@RichardFriend You are correct. I'm unable to create WCF RIA Services. in WPF. I agree with you that there are to many which your entities and I dont favor DTO because of mappings and additional classes. I also have a question. Do you have methods in that EF poco or are you just using properties which is my case. Ill edit my post a bit to clarify. Regarding your issue. I do not know how many entities you might have. But you might be able to create an Entity.Infrastructure project for each of your entities. This would prevent module dependecy but only entity infrastructure dependecy.Quadrennial
We have loads of entities and my main concern is not the DTO side as im only exposing POCOS anyway, my main concern is exposing the auto generated entity proxies to the rest of the application, i dont want this type of leaky abstraction, i want my application service to hide the implementation of how it gets and saves its data (via the wcf service). I had a thought, my EF POCOS could be re-used as my domain objects so it would go EF POCOS->WCF service proxy object->EF POCOS using automapper to translate from the service proxy objects back to my POCOs.Laudianism
G
0

You can define an IPerson interface, have your entity implement it (using partial classes), and use that in your contract. The other option, if you prefer, is to split out your entity definitions into their own assembly, or just include them in your contracts assembly.

Gradygrae answered 3/4, 2012 at 13:0 Comment(4)
I did think of that, and i like the idea, however its an awful lot of work to create these interfaces and keep them in sync with the data model, when you consider that the entities are auto generated.Interested to see how other people approach this.Laudianism
Can't you auto-generate an interface, too? At least as a starting point that would save you a lot of typing.Gradygrae
what about creating new entities, i would have to register the concrete entity against its interface and use ServiceLocator or unity container to resolve, this just feels wrong..Laudianism
@Richard: it really depends on the design of your services. For example, you can push the responsibility for creation into the service itself. Also, you may have missed my updated answer regarding putting the entities themselves into your contracts.Gradygrae

© 2022 - 2024 — McMap. All rights reserved.