WebApi receiving model with references (Not attached to Context) - c#

I am trying to pass a complex type to WebApi having this on my ApiController :
[HttpPost]
public void DoSomeCrud(JObject data)
{
ComplexModel item = data.ToObject<ComplexModel>();
// Do some logic here
}
My issue is that one of the properties I have inside my ComplexModel is an Entity Framework entity. I don't have problems passing that entity if detached, however as soon as I get that entity from DbContext the model cannot be passed to WebApi as expected.
My question is.. : Is there anyway to detach my entity preserving my references to foreign keys ? Because I need those references on the WebApi side.
Thanks

It is not best practice to use model from entity framework as data transfer object (Dto) for Web Api because you can get problem with serialization since models from EF are actually proxies which supports lazy loading and navigation properties (if you don't detach it).
The best practice is, for separation of concern, you should define your own Dto objects instead of using entity models directly from EF.
Simple example, if you have Customer entity, you also should have CustomerDto entity which projects any property from Customer you want.

Related

Is it really necessary to ignore self-referencing loops while using many-to-many relationships in ef core?

I'm trying to set up a many-to-many relationship on ef core following this model:
https://stackoverflow.com/a/46184785/11234800
But every time I try to query a person with all its clubs from this relationship, as follows:
public async Task<IList<Person>> GetAll()
{
var query = _dbContext.Set<Person>()
.Include(pc => pc.PersonClubs).ThenInclude(c => c.Club)
.AsQueryable();
return await query.ToListAsync();
}
I end up running in a self-referencing loop error, which I solved by doing this: https://stackoverflow.com/a/34847316/11234800
Is it really necessary to ignore this type of error or there's a better way to solving this issue?
IMO the self-referencing loop issue is only a result from a poor design choice in your application.
I would recommend you not to return the entity which is connected to EF and instead return a model which represents the application endpoint interface, a data transfer object.
That object will only present the necessary data, which should be presented from that specific endpoint.
For example, if you return the Person entity as you do, is the relation property PersonClubsId really needed to represent a person?
Or for instance, if you have some metadata field like CreatedDate, CreatedBy. Those should most likely not be included.
Instead create your own class which will represent a Person with the properties that represents your entity in the best way.
Another reason why you should decouple the EF entity from your application endpoint interface is because if you make any changes in the db-structure for your Person entity,
those changes will be reflected upon the client as they both uses the same model.

MVC Mapping layer accessing Service layer

I have designed my application (ASP.NET MVC with EF6) so there is a Mapping layer responsible of holding mappings from Entities to ViewModels back and forth. It is used by the Controllers, so basically the usual Edit action looks like
var entity = DataService.Get(viewModel.Id);
entity = Mapper.MapToEntity(viewModel, entity);
DataService.Update(entity);
The base MapToEntity implementation uses AutoMapper to map the basic properties of the object.
Update() is implemented in EF6 as a function which marks the entity as modified and calls the underlying context SaveChanges().
However, for more complex mappings, like entities with related entities, e.g. an Order, the Mapper class performs more operations. For example, updating the related entity objects (OrderDetails) with the ViewModel related object data, assigning the parent Id (OrderId) to the new child objects, and finally the problematic issue: deleting a child object.
Right now, my specialised Mappers have a reference to the Service Object of the related entity, which has a MarkEntityToDelete function, called just to mark in the underlying DbSet that entity for deleting.
foreach (var orderDetail in viewModel.OrderDetails.Where(d => d.Id != 0 || d.Delete == false))
{
var orderDetailToUpdate = orderDetail.Id == 0 ? new OrderDetail() : _orderDataService.GetOrderDetail(orderDetail.Id);
if (orderDetail.Delete)
{
_orderDataService.MarkLineaAsDeleted(orderDetailToUpdate);
}
else
{
Mapper.Map(orderDetail, orderDetailToUpdate);
if (orderDetail.Id != 0) continue;
orderDetailToUpdate.MantenimientoId = order.Id;
order.OrderDetails.Add(orderDetailToUpdate);
}
}
This is a dependency which is only there because the implementation uses EF6 and the transaction border is inside the Service, so the Mapper cannot directly delete the object, just mark it for deleting.
Although this solution works well in practice, I don't particularly like it very much. I don't think the Mapper object should have a dependency on a Service object in this way, just to mark a child object for deleting.
I tried to use the following code:
entity.EntregasCuenta.Remove(entity.EntregasCuenta.Single(e => e.Id == entregaCuenta.Id));
but it gives a foreign key check error, which is expected, as I don't delete the related entity but the relationship.
So my question is, how should the mapper deal with this situation? Mapping from a ViewModel to the Entity should be done by a Mapping layer, but updating the related entity should be done by a Service. Finally, the Controller responsibility should be only to call the three operations in order, that is, retrieve entity (service), map viewmodel data to entity (mapping layer), update changes (service).
Am I missing something?

Design considerations for using EF objects in ASP.net MVC

I am using EF code first in one of my mvc 3 projects. I have a question about what patterns to use when passing a complex EF POCO object to and from the views.
For example, a customer object has a list of orders and each order has a list of items. The customer object will be sent to the view. The view updates the customer object and its inside objects (orders, items), then send it back the controller. The controller have EF to persist the customer object.
My questions are following:
Should I serialize the EF poco object to a JSON object so I can use it inside the view?
How can I re-construct the customer object when I recieve updates from view?
After the customer object is reconstructed, Is it possible to save the entire object graph (customer, orders, items) in one shot?
Thanks
I tend to stay away from using the EF POCO objects as the model for my views. I generally will create View Models from one or more POCO objects as what I need in a view never matches exactly a single EF POCO object. The view models will then create the EF objects that are then saved to the DB.
Should I serialize the EF poco object to a JSON object so I can use it inside the view?
No.
How can I re-construct the customer object when I recieve updates from view? Don't. Let the default modelbinder materialize the POSTed data into a viewmodel (or editmodel), and use that data to issue commands to a lower layer.
After the customer object is reconstructed, Is it possible to save the entire object graph (customer, orders, items) in one shot? It is, but you shouldn't. Instead, deal with each update individually based on your use cases.
Follow mojo722 and Pluc's advice here. Don't use EF POCO entities in your MVC layer. Use viewmodels. Here's how it would work:
Controller needs data, it asks a lower layer. The lower layer gets the data and returns entities (or better yet, entity views).
Controller converts entities to viewmodels (AutoMapper is good for this, but you can map manually as well).
Controller passes viewmodels to view.
View sends HTTP POST data from HTML form.
Default model binder converts HTTP POSTed form data to a viewmodel.
Controller receives viewmodel data, issues a command to the lower layer.
Lower layer uses EF to save new entity state.

Entity Framework Partial Classes Instantiate by Id / Primary Key

I'm using Entity Framework 4.1. I have a normal model .edmx which maps a Match class to a 'Match' database table and this can be accessed as normal using EF.
However I require custom properties methods for the Match so I extended this using a partial class and I can add my properties etc.
All of this works fine, however I just can't find out how to instantiate an instance of my partial match class by its primary key / id. i.e so I can pass the Id into the constructor and have the object populated with all of its data from the database.
I know we can do the following to populate from calling code:
public Match PopulateforMatchId(int matchId)
{
var match = (from m in _db.Matches
.Include("TeamA")
.Include("TeamB")
.Include("Season")
.Include("Season.Competition")
where m.Match_ID == matchId
select m).FirstOrDefault();
return match;
}
However this is not what I need as this is not self contained within the partial class itself, I need it to populate itself, as other properties in the partial class rely on the object itself having its data in place before they can be calculated.
Anyone have any ideas how i can do this?
Thanks
Kevin
This is wrong way to use Entity framework. Entity framework is not suitable for easy populating existing object. Moreover it demands that entity has internal dependency on the EF context.
How to probably make it work (but I definitely not recommend it):
public Match(int matchId)
{
// You called constructor yourselves = you have unproxied entity without
// dynamic change tracking and without lazy loading
Id = matchId;
// I'm not sure if this is possible in entity constructor but generally it should work
// Get context somewhere - service locator pattern
ObjectContext context = ContextProvider.GetCurrent();
context.Matches.Attach(this);
context.Refresh(RefreshMode.StoreWins, this);
// Now you should have populated Match entity itself but not its navigation properties
// To populate relations you must call separate query for each of them because `Include`
// is possible only when the entity is created and loaded by EF and lazy loading is off
// in this case
context.LoadProperty(this, m => m.TeamA);
context.LoadProperty(this, m => m.TeamB);
Season = (from s in context.Seasons.Include("Competition")
select s).ToList();
}
This is also the example of wrong constructor - constructor should not take such heavy logic. It should be responsibility of some other initialization method.

Entity Framework 4 - Repository Pattern - How to avoid full load of entity with nested relation

I'm currently working with Entity Framework 4 and the repository Pattern in c#.
I have an entity (Category) which contains a property (Main Category) which refers to the Main Category and some other stuff.
Because of navigation property, the main category has access to their childs category.
For reasons I'll explain later, I disabled lazy loading.
When I try to get a category with his id and because of navigation properties, EF4 load the whole graph whereas I just want to load the targeted category and not the related (parent or child) entity.
I want to do this because this entity is aimed to be converted into a dto and used in a WCF WebService. The full load of graph is not compatible with my approach.
Is there a way to avoid loading of nested entity with EF4? If not, can NHibernate be made to work that way? (I was thinking that disabling lazy loading will allow me to have full control on what I want to load (explicit or eager loading) but it seems not ...)
Why don't you project your entity object into that dto object when you get the results from the object context itself? You can use something like
myclient.Select(c => new clientdto(){ name = c.name, email = c.email, phone = c.phone})
which will return the Ienumerable of the clientDTO object.

Categories

Resources