Handling transaction data at ASP.NET Web Api - c#

I want to build server for Point Of Sales which is going to be on top of Web Api asp.net
My plan is to have one controller for bills.
For handling bills from web-api post to sql server I am planing to use micro ORM PetaPoco.
One bill is going to be written in database at three tables.
PetaPoco pushing me to have three "pocos" for-each table one.
I want to write these three pocos to database inside transaction.
How I shod design my controller and classes to looks nice also work nice.
Should I ?
Make my controller accept three (3) classes for for parameters, Is this possible at asp.net web api at all ? Can I deserialize from one request three different classes ?
Make my controller accept one class, after that on server side from that class make three pocos which is going to be written to Database server ? Can someone post how wold looks like that class which is going to be split at three parts ?
Make my controller have three methods for posting separate data (bills-header, bills-payment, bills-articles) one by one ?
Perhaps it will be so hard in this case to have one transaction for three separate calls?
Any other approach ?

I would definitely go with option 2 - since your web client should be agnostic of the implementation details - i.e. whether you are persisting to one table or 3 tables shouldn't really matter to the client.
The controller or the service method would look like this (obviously the naming is not great - you'll have to modify it according to your domain lingo):
public void AddBill(BillDTO bill)
{
//Map the DTO to your entities
var bill1 = mapper1.Map(bill);
var bill2 = mapper2.Map(bill);
var bill3 = mapper3.Map(bill);
//Open the transaction
using (var scope = db.Transaction)
{
// Do transacted updates here
db.Save(bill1);
db.Save(bill2);
db.Save(bill3);
// Commit
scope.Complete();
}
}

You should read about DTO pattern, it would answer some of your questions:
1. WebAPI supports it.
2. That sounds like DTO, so it is a good solution, as you hide your persistence model from consumer.
3. There's no point to force consumer to make three calls, each call has own 'infrastructure' cost, so it is better have one infrastructure cost instead of one.

Related

WEB API & BL relations

My project structure is Client <=> Web API <=> BL <=> DAL (Repository) <=> DB.
Does it make sense that one API will know many BLs? Meaning that in one API method it will call to X_BL and in another method, at the same API class it will call to Y_BL? If it makes sense, can you please provide an example?
Or is it always should be 1:1 relation, so that each API controller will call to its BL, for example: CustomersAPI will always call to CustomersBL, and ProductsAPI will always call to ProductsBL.
In my opinion the answer it's depends, there are many questions that need to be answered first
What do you make a API for ?
Do you have to follow the architectural design patterns owned by API users (E.g. MobileApp, WebApp) ?
Or just want to make an API that only provides data in like you said, 1:1 relation, so the other app must follow the architectural design patterns you make ?
Where you focus on processing data, client side or server side ?
What are the limits of the work scope of the API and its users ?
In my experiences, if you want to make a scalable REST API, your controller must be able to access any BLL (Business Logic Layer) when it's needed. BLL = BL (in your case)
E.g. :
http://localhost/customers/15
The customers controller only needs 1 BLL (CustomerBLL) to find a customer with ID 15 then return the result. Like you said, 1:1 relation.
In the other case, you'll need more than 1 BLL.
E.g. :
http://localhost/customers/15/products
The customers controller needs another BLL (ProductsBLL) to find any products that related to customers with ID 15 then return the result.
It absolutely makes sense, APIs often require multiple pieces of business logic to solve a particular problem. For example, your CustomersAPI may talk to a CustomersBL, but also talk to a UsersBL to get the authorization context (which customers can be returned), or to a CRM BL when actions are performed.

Entity Framework Core and REST client - code organization

I'm building a solution with three projects:
.Data (holds Entity Framework Core-classes and Writer.cs)
.ConsoleApp (Startup project, calls Writer.cs)
.CloudTalker (Web Services references and Fetcher.cs)
The purpose of the solution is to call REST APIs, get entities from the APIs and store them in a database using Entity Framework Core. All code is running fine but I am positive there are ways to improve the architecture.
Example code flow to fetch Customers from the REST API and write to the database:
Program.cs in .ConsoleApp instantiates Writer.cs and calls method WriteCustomers().
WriteCustomers get the latest modified date for Customers in the database
WriteCustomers calls GetCustomers( latestModifiedDate ) in Fetcher.cs in the CloudTalker project. This method returns and array of Customers (the class returned by the REST API, not Entity Framework).
WriteCustomers loops through the array, converts the REST-object to an EF Core-object and puts it in _context.Customers.
Context.SaveChanges() stores the Customers in the database.
Now to my questions/calls for opinions:
Have I done a decent separation of concerns? What is bugging me is that either the CloudTalker needs to know about the EF classes or the EF classes needs to know about the REST classes. Which way is preferred? Should CloudTalker.Fetcher.GetCustomers( lastModifiedDate ) return objects from the EF Classes or the REST type?
How should I handle naming of the classes? Right now I have two Customer - the REST kind and the EF kind. Not pretty.
Anything else I should do differently?
Thanks in advance for sharing any insights.
Seems to me that this should belong to codereview website but here's what I think about the architecture (I am disregarding the fact that this could be a simple project that can live with a quick and dirty solution)
The writer should be in a separate project and should only know about EF and DB, The fetcher should only know about REST and how to call remote services. You can then introduce a service layer that knows about the two former bricks and calls the fetcher to get the data, then pass the data to writer.
I assume there's no business logic so no need for a separate domain project. Your service layer can be directly in your UI/Console project.
For the naming, how about CustomerReadModel, CustomerWriteModel?
It seems that you also need to read from DB to get the last modification date, so I would suggest having a reader somewhere in your db project.

How does it work the Session Per Request pattern?

We're working on a project using ASP.NET MVC4. In one of team's meeting, came out an idea of using Session per request
pattern.
I did a little search and found out some questions here in SO saying - in general - that this pattern (if may be called) it's indicated to frameworks ORM.
A little example
//GET Controller/Test
public ActionResult Test()
{
//open database connection
var model = new TestViewModel
{
Clients = _clientService.GetClients(),
Products = _productService.GetProducts()
};
//close database connection
return View(model);
}
Without session per request:
//GET Controller/Test
public ActionResult Test()
{
var model = new TestViewModel
{
Clients = _clientService.GetClients(), // Open and close database connection
Products = _productService.GetProducts() // Open and close database connection.
};
return View(model);
}
Doubts
To contextualize, how does session per request works?
Is it a good solution?
What is the best way to implement it? Open the connection on web?
Is it recommended in projects with complex queries / operations?
Is there a possibility of giving a concurrency problem when transactions are involved?
Looks like you mean "DB context per request". You can achieve it with Unit of work pattern.
Simple implementation of that you can check int this article of Radu Pascal: https://www.codeproject.com/Articles/243914/Entity-Framework-context-per-request
Another implementation (for Entity Framework and NHibernate), you can find in ASP.NET Boilerplate which is more complex: http://www.aspnetboilerplate.com/Pages/Documents/Unit-Of-Work
In a web (web application, wcf, asp.net web api) it is a good idea to use one DB context per request. Why? Because the requests are short lived, at least that is the idea or your application will have a slow response time, so there is no point in creating many db contexts.
For example, if you are using EF as ORM and you issue a request to Find method, EF will first search for whatever you are asking in the local cache of the db context. If it is found, it will simply return it. If
not found, it will go to the database and pull it out and keep it in the cache. This can be really beneficial in scenarios where you query for the same items multiple times until your web application has fulfilled the request. If you create a context, query something, close the context then there is a possibility you will make many trips to the database which could be avoided.
To elaborate further, imagine you create many new records: a customer record, an order record, then do some work and then based on whatever criteria you create some discount records for the customer, then some other records, and then some orderitem records. If you use the Single Context Per-Request approach, you can keep adding them and call SaveChanges at the end. EF will do this in one transaction: either they all succeed or every thing is rolled back. This is great because you are getting transactional behavior without even creating transactions. If you do it without Single Context Per-Request approach, then you need to take care of such things yourself. That does not mean in the Single approach, everything needs to be in one transaction: You can call SaveChanges as many times as you want within the same http request. Consider other possibilities, where you pull a record, and later on decide to edit the record and then edit it some more: again in the Single approach, it will all be applied to the same object and then saved in one shot.
In addition to the above, if you still want to read more then you may find this helpful. Also, if you search for Single Context Per-Request, you will find many articles.

What is the standard I should use in MVC coding

Based on the answers mentioned here, I understood that I should put the business logic inside the model itself, while in my program I am using EF directly inside the actions of the controller for example to get the list of cars from the database directly I am doing the following:
public ActionResult CarList()
{
using(var _db = new CarRentEntities())
{
var result = _db.Cars.Where(m=>m.Active);
return View(result);
}
}
what is the impact on my website performance if I will use the mentioned above code inside controller or inside Model?
which method I should use? for example if I want to work with a team, is there a standard I should follow to separate the code, kindly advise
for using the repository pattern: I read that we should not use if as mentioned for example here , i will copy some of what mentioned:
The single best reason to not use the repository pattern with Entity
Framework? Entity Framework already implements a repository pattern.
DbContext is your UoW (Unit of Work) and each DbSet is the repository.
Implementing another layer on top of this is not only redundant, but
makes maintenance harder.
if my database contains the following tables: Manufacturers , Cars , Rent , Clients , rent class is the a table with 2 foreign keys between Clients and Cars and contains other detailed fields.
how to deal with Rent Object which need to get data from 2 different repositories Cars and Clients in order to display the renting grid based on search criteria entered by the user, if I will use the repositories Cars and Clients , they have their own dbContext, BOOM my head cannot understand this technique, kindly advise
The answer to your question is, it does not really affect performance but it will definitely become an issue in terms of maintainability as the application grows bigger. You can adopt the SOLID architecture principles: SOLID architecture principles using simple C# examples. This enables you to develop high quality software.
You can create a multi-layered application:
Interface Layer - MVC application
Business Layer - Class Library with classes with logic
Data Access Layer - Database Contexts and Repositories, unit of work with CRUD operations
Shared layer - Logging, AppSettings, validations, utilities, extensions, constants, enums
Having your application in this structure would require you to consider things like inversion of control, dependency injection and many more to ensure loosely coupled classes, easy unit testing and most of all a solid application.
You can also read this: Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application
Generally the Model is a "unit" - i.e. it is a model of the data you want to display. The Controller is an "integrator" - i.e. it pulls together the various resources required to render your web page. You may wish to create a database fascade class which does something like this;
public ActionResult CarList()
{
using(var carStore = new Factory.CreateCarStore())
{
var result = carStore.GetActiveCars();
return View(result);
}
}
To separate your database access from your web controller (this would make it more test-able as well because you can substitute a different CarStore implementation (i.e. a Test XML data set) for testing purposes.

SPA Hot Towel: Multiple Database Context

I am new to SPA hot template and I am trying to use multiple connection strings (multiple database context). Most examples online use only one as follows
[BreezeController]
public class MyController : ApiController
{
readonly EFContextProvider<ContextClass> _contextProvider =
new EFContextProvider<ContextClass>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
...
What is the best way of implementing something like this where I use a repository, Unit of work and am able to join object from different content?
Let's separate (1) the Repo/Unit-of-Work issue from (2) the multiple-database issue.
Server-side coding practices
What you describe appears only in demos. The server code exists to facilitate the client-development story which is the point of these BreezeJS samples. We made no effort to illustrate proper server side coding practices. In fact, we're often showing bad practices.
We're not ashamed. We want your full attention on the Breeze client. A functional server is all we need and "doing it right" would require more code and distractions that have nothing to do with writing a Breeze client.
For the record, I would NEVER create an EFContextProvider in the controller of a real app. The controller should concentrate on mediating client requests.It should be thin. Repository or UoW classes (and helpers) in separate projects would handle business logic and persistence.
The EFContextProvider itself is production grade and appropriate for most applications that turn Breeze client requests into Entity Framework persistence operations.
Multiple databases
If you do all of the joining on the server, your web api (little "w", little "a") can present a single face to the client and you'll only need one set of metadata to describe a model that persists across multiple databases. That's great for client development and is probably the most productive approach, given that you'll have to validate and coordinate cross-database query and save operations on the server no matter what you do on the client.
There is no escaping the fact that your server will be much more complicated than if you had one model, one DbContext, and one database. Too bad you can't separate the workflows so that you have only one model/context/database per feature area. You'll probably lose the ability to use IQueryable and have to write specific endpoints for each query that your client app requires. Oh well.
I smell a deeper architectural problem. But the real world presents us with stinky situations; we must hold our noses and persevere if we possibly can.
At least you can shield the client by managing the mess entirely on the server. That's what I'd try to do.

Categories

Resources