SOA architecture for ASP.NET with Entity Framework - asp.net

I am redesigning a solution's architecture to implement SOA.
After doing the design changes I have come up with:
MySolution.Client.MyProject.Web ...... //ASP.NET WebSite
MySolution.Client.MyProject.Proxy .... //Service Proxy C# Library Project *1
MySolution.Service ................... //Service.cs for Service.svc is here
MySolution.Service.DataContract ...... //IService.cs for Service.cs is here *[2]
MySolution.Service.HttpHost .......... //Service.svc is here
MySolution.Model ..................... //All custom data classes and EDMX model is here *[3]
MySolution.Repository ................ //Repository queries the DB using LINQ and ADO.NET queries
*1 MySolution.Client.MyProject.Proxy:
This project contains service proxy and contains presentation classes
*[2]MySolution.Service.DataContract:
This project contains IService and Request/Response Classes
All methods in Service.cs takes the Request classes as input and return Response classes as output
Therefore this project is referenced by the 2 Client Projects(Web and Proxy), as it contains the IService and all of the Request/Response classes that will be required to communicate with Service.cs
*[3]MySolution.Model:
This project contains the .edmx that is the Data Model of Entity Framework and some custom classes that are used in the project.
PROBLEM:
Because I only use request/response classes to communicate between service and client, the MySolution.Service.DataContract project is only used by Service.cs and Repository.cs
And due to that all responses that Repository generates I have to map them to the properties of its respective response class (which make both the original returned entity, and the response class almost identical). But I am OKAY with it...
For example:
The GetCustomer() in Repository.cs method is called by Service.cs
The GetCustomer() method in repository performs the LINQ query and returns a "Customer" object
Service.cs then maps all the properties of "Customer" object to the "CustomerResponse" object
Service.cs then returns the "CustomerResponse" to the caller.
In this case, most of the properties will repeat in both classes. If there is a solution to this, it's good, otherwise, I am fine with it.
However, when Repository.cs's method GetCustomers() (Notice it's not GetCustomer()) is called, it will return a list of Customer objects, and mapping this for return purposes would mean a "for loop" that iterates the collection and do the mapping... This is NOT OKAY...
Is there a better way of doing this, considering I do not want to return "Customer" object without "CustomerResponse" as first of all it violates the SOA architecture, and secondly I don't want my client projects to have any reference to the Model or Repository projects?

So is it just the mapping that you're having trouble with? If so, you could look at some open source mapping libraries like Mapper Extensions or AutoMapper that will automate the task.

If you don't like separate mapping between entities and DTOs expose IQueryable in your repository and use direct projections to DTOs. The disadvantage is that such solution can't be effectively unit tested. Mocking repository in such scenario doesn't make sense because query agains mock is Linq-to-objects whereas query against real repository is Linq-to-entities (different set of features where difference can be seen only at runtime).
Btw. I don't see too much SOA in your application - I see just multi tier application. It is like planting a tree in a garden and saying that you have a forest. Moreover it sounds like you are building CRUD interface (entities almost 1:1 to DTOs). I have a bad feeling that you are investing too big effort to architecture which you don't need. If your main intention is to build CRUD operations exposed as services on top of database you can expose entities directly moreover you can use tools like WCF Data services.

It sounds like your main point of grief is the tedious mapping of data objects to data transfer objects (DTOs). I haven't used this myself, but it seems like AutoMapper is made for doing automatic object-to-object mappings declaratively.
I would definitely stick to having your data objects separate from the data contracts in your services.

Related

hiding method from certain layers in project

I was looking through an old project and wanted to see if anyone had a suggestion on how to hide certain methods from being called by various layers. This was a 3 tier project, webapplication -> web service -> database
In the application there is a User object for example. When a User was being updated, the webapplication would create a User object and pass it to the webservice. The webservice would use the DataAccessLayer to save the User object to the database. After looking at this I was wondering if instead I should have made a Save method in the User class. This way the service and simply call the Save on the User object which would trigger the db update.
However doing it this way would expose the Save to be called from the webapplication as well, correct? Since the webapplication also has access to the same User object.
Is there anyway around this, or is it better to avoid this altogether?
There is a separation of concerns by keepeing the User object as object that only holds data with no logic in it. you better keep it separated for the following reasons:
As you stated, it is a bad practice since the Save' functionality will be exposed to other places/classes where it is irrelevant for them (This is an important for programming generally).
Modifying the service layer - I guess you are using WCF web service as you can transfer a .NET object (c#/VB) to the service via SOAP. If you put the saving logic in the 'User' object, you can't replace it another webservice that receives a simple textual data structures like JSON or XML or simply doesn't support .NET objects.
Modifying the data storage layer - If you want, for example, to store the data inside a different place like other database such as MongoDB, RavenDB, Redis or what ever you want, you will have to reimplement each class that responsible for updating the data. This is also relevant for Unit Testing and Mocking, making them more complicated to interrogate.

Web Services Model

I have 1 Site (MySite.com) / 1 Web Service (WebService.MySite.Com) and one Common Library (LibCommon)
The common Library Contains a Model e.g. UserModel = LibCommon.UserModel
The web service has a method 'Void CheckUser(LibCommon.UserModel model)'
However when I add the 'WebService' reference to 'MySite.com' the method changes so that it looks like 'Void CheckUser(WebService.MySite.Com.UserModel model)'
So I think fair enough I can just cast one object to the other as they are identical however .NET Says I cannot do this?
Is there a work around for this?
Cheers,
Note this is for WCF, and not ASMX web services:
You can't directly cast the original data class to the proxied class generated by the WCF service reference wizard. However, you can reuse the original data class in the client:
Add the library reference containing the transfer objects (i.e. LibCommon) as a reference to both the Service (WebService) and the Client (Mysite.com). When adding the service reference on the client, choose the advanced tab and then select Reuse types in referenced assemblies. This will then reuse the common data transfer classes, instead of duplicating the types with proxies.
Note however that by eliminating the proxied data class, you are introducing direct coupling between client and server - you should do this only if you have control over both client and server w.r.t. version control issues etc (e.g. able to deploy new versions of both client and server simultaneously)
As an aside, it is also possible to eliminate the shared service interface as well, by moving the server side Service contract interface into a separate, common assembly and then using a technique such as this or this.

Creating 3 -tier In MVC3

I am creating an Simple Application where A user register his/her name and After Registration he/she Redirect to Login Page ang after login he/she redirect to the Home page.
A Simple Application as i said..
But My concern is that I want to Implement this In MVC3 But using 3-tier Architecture.for this I created A MVC3 Project named it as Presentation and Created a New Project under Solution and named it as DAL and Shifted the Model Folder in DAL where i have created all the Properties and DbContext and Controller and View in Presentation.So can any one tell me what to keep inside BLL Folder?Please Suggest me!!!
One solution would be to use MVC as a Presentation layer (as you are doing it right now). Inside of your MVC there will be cases when a model would not be sufficient for you in which case you will need to create ViewModels. You can move the ViewModel to the business layer in which case when BLL retrieves data from DAL, it converts it into some ViewModel with some functionalities and defaults, and send it over to the presentation layer. Once the presentation layer finishes with using the VMs, it passes the data to the BLL which can perform some special validation and some extra business logic. After that it would create model(s) by extracting data from VM and pass it to DAL which can perform transactional update, delete or insert.
Normally my solution at minimum has five projects. I have API project, MVC, Business Layer, Data access layer and Resources.
API
This project contains models, interfaces, abstract classes, etc. In essence it contains everything that other layers need to implement. There is usually IRepository for the Repository Pattern implementation, IUnitOfWork for the Unit of Work pattern, models which are either generated by Entity Framework or by hand (but no mappings). ViewModels are also here together with extension methods for converting to and from the models.
Business Service Layer
This layer is in charge of fetching the data from the data access layer, converting it to the view model by invoking extension methods, initializing values. Also, if a DAL returns null value, the business service layer will not pass it over to the presentation layer as null, but will return an implementation of the Null Object Pattern. The Null Object Pattern is actually implemented in API and is called by business service layer. This layer references API layer.
Data Access Layer
Here you normally implement the repository and unit of work patterns. Instead of directly communicating with EF, you would wrap calls to DbContext into these two implementations. In addition to this, mappings from models to SQL Server tables and columns, as well as foreign keys are done here. This layer references API layer.
Resources
All the resources, strings, language translations, etc are located here. This project does not reference API, but Business Service Layer, Data Access Layer and Presentation Layer reference this project to get access to the strings.
Presentation layer
This is normally an MVC solution (or if it is Web Forms then there it will be implemented using MVP patter). This solution communicates with Business Service Layer. It receives ViewModels and return values from the business layer. It passes the view models if they are valid to the business layer in order to have them persisted.
Linking layers
The layers are connected among themselves using dependency injection. I usually use Unity and configure my application using external configuration settings. This way the Presentation layer, business service layer and data access layer do not have explicit reference. MVC does not hold a direct reference to BLL, BLL does not have a direct reference to DAL. The constructors for controllers and BLL and DAL classes use interfaces and unity passes the appropriate implementation.
You will probably put any Helper methods, Library code or re-usable business logic that the that the controllers use. I often put utility classes and validation logic in here plus any functionality that works with the data obtained from the DBContext Entities.

NHibernate - Business layer testing with in-memory SQLite database. How to change database configuration?

I use Fluent NHibernate code to create a MySQL database SessionFactory. No config files (just one value for the connection string in configuration - connectionStrings section of configuration file).
The SessionFactory creation code is contained in a Data tier class: SessionFactoryManager, which implements a singleton internal SessionFactory which is used by the Data and Business tiers to get all the sessions via SessionFactoryManager.OpenSession().
Some of my Business tier methods internally call SessionFactoryManager.OpenSession() to create sessions in a way that is transparent to the Presentation layer. So, when calling this methods there is no parameter or return value involving a session (to keep the Presentation layer "session-agnostic" when using those Business tier methods).
My problem comes when I write the integration tests for the Business layer: I would like to make them run on a SQLite in-memory database. I create a SessionFactoryManager which uses Fluent configuration to configure the SQLite database.
But when testing those methods that internally create the session, I can not tell them to use my testing SessionFactory (configured to use SQLite). So the "real" SessionFactory is called, and so the MySql database is used, not the SQLite.
I'm thinking of several possible solutions, but none of them seems right.
I could migrate the NHibernate configuration in Data layer to config files, and make different NHibernate config files for development/production and test environments, but I really would prefer to keep on with Fluent code.
I could also modify my Data layer to use a single configuration value, databaseMode or similar, that sets the database to be used: testing in-memory or the real one. And write some switch(databaseMode) statements like "case inMemory: { ... fluent code for in-memory SQLite... } case standard: { ... fluent code for standard database ... }". I don't like this approach at all, I don't want to modify my Data tier code functionality just for testing purposes.
Notice that I'm not testing Data layer, but Business layer. Not interested in testing NHibernate mappings, Dao or similar functionality. I already have unit tests for that, running OK with SQLite database.
Also, changing database is not a requirement of my application, so I'm not quite interested in implementing significant changes that allow me to dynamically change the DBMS, I only came to this need in order to write the tests.
A significant point: when using in-memory SQLite the database connection must be the same for all new sessions, otherwise the database objects are not available to the new sessions. So when creating a new session with SessionFactory.OpenSession() a parameter "connection" must be provided. But this parameter should not be used with non in-memory database. So the switch(databaseMode) should be used for any single session creation! Another Data layer code change that I don't like at all.
I'm seriously considering giving up and running my tests with the real database, or at least on an empty one, with its objects created and dropped for any test execution. But with this the test execution will surely be slower. Any ideas? Thanks in advance.
Finally my solution was Inversion Of Control: I changed my data tier so I can inject a custom SessionFactoryBuilder class that makes the Fluently.Configure(...) magic.
In my data tier I use the "real" MySqlSessionFactoryBuilder, in my test projects I write TestMySqlFactoryBuilder or TestSQLiteSessionFactoryBuilder classes, or whatever I need.
I still have problems with SQLite feature that requires that the same connection is used for all sessions, and must be passed as a parameter in every ISession.Open() call. By the moment I have not modified my data tier to add that feature, but I would like to do it in the future. Probably by adding to my SessionFactory singleton a static private member to store the connection used to make SchemaExport, and a static private boolean member like PreserveConnection to state that this connection must be stored in that private member and used in every ISession.Open(). And also wrap ISession.Open() and make sure that no session is opened directly.

ASP.NET MVC - Using UnitOfWork

I'm currently working on a web app which consist of 6 layers:
Web (reference to ViewModels and Controllers)
ViewModels
Controllers
Services (reference to Data and Entities)
Data (reference to Entities)
Entities
What I'm trying to is to implement a "UnitOfWork" pattern, and therefore I have a class thats injected by DI for that job which makes it possible to do .commit() in the actionresult in the controller when I'm done with the database.
Now is my question... Where should this UnitOfWork class be placed? It's at the moment in my Data layer but that requires the Controller layer to reference the Data layer AND the Service layer, which is odd in my opinion... Should I move the UnitOfWork class/interface to the Service layer and use DI?
Unless you're using the Repository pattern in your Data layer, you're wasting your time.
The point of a UoW is to handle changes across multiple Repository instances, this is done in the following ways:
Unit of Work derives from the actual underlying context (DataContext - L2SQL, ObjectContext/EF)
Repositories take a Unit of Work in their ctor.
The Unit of Work do two things:
Have a Commit() method
Expose the underlying object/entity set to the Repository.
It's a little tricky to get it all setup, but once you do, the flow should be like this:
Controller get's DI'ed a service and a unit of work (both via Interfaces)
Controller calls method on a service ("CustomerServices.AddOrder()")
Service calls method on Repository
Repository calls "Add" method on "Order" object/entity set
Controller commits Unit of Work
Essentially, each layer takes an instance of the "next layer" in their constructor. Everything should be DI'ed and interface-driven. The UoW has not reliance on anything - but the Repository relies on it for persistence to the "internal memory" (ORM), then the UoW "Commit" will push the changes out to the database (basically wraps the "SaveChanges" method).
As the Unit of Work is an infrastructure/persistence/database/transactional concern, it should go into your Data layer. Should only be referenced by Controllers.
I implemented my IUnitOfWork class to be passed directly into my MVC controllers (injected via Castle Windsor). I then have my controller pass it to any service objects it instantiates.
IUnitOfWork should be an interface for data layer. When request come into Controller then call service methods, if you require CRUD there should call UnitOfWork. You may use Session Per Request by call UnitOfWork in Global.asax Request_Start and commit works in Request_End.

Resources