Using pocos to update database - serialization

Using ASP.NET WebAPI, and EF 5.0. I've created a data provider that will query the database and then return an object or collection of objects to my client, which happens to be an html5/angularjs app.
The problem is with the updating. So for example, if I have a Course, which can have many Students. So I have a Course table and a Student table with an fk to StudentId. If I need to edit a student, the EF objects contain everything about a student, including the CourseId, and the Course object itself.
Because of this looping reference, WebAPI pukes when trying to serialize this data, so lazy loading is off- so when I get my Student poco, Course is null.
And then when I update that Student on the client side and then PUT back to my WebAPI, I can't update the DB due to A referential integrity constraint violation occurred.
I could make DTO's but before I go that route are there other patterns I should look at to overcome this problem? Suggestions on other tools or packages to simplify this?

The WebApi struggles serializing the EF object graph but you should be able to update the entity even without navigation properties are null as soon that your object got a valid Id.
Ensure you are attaching it correctly to the context by setting it state to modified:
public void Update(DbContext context, User user)
{
context.Entry(user).State = EntityState.Modified;
context.SaveChanges();
}

Related

How can I check whether or not EF Core has queried the database for an object with the same Id in different phase of a request?

For example, my API controller action logic might retrieve a User object by its Id as the first step. Then after some processing, within the same http request, I need the User instance with the same Id again. Somehow the User object can't get passed all through. So at this point, when I call something like dbContext.Users.Find(1) again, how can I know for sure that the DbContext doesn't have to query the database again and instead use the Local tracked version of this User object?
So at this point, when I call something like dbContext.Users.Find(1) again, how can I know for sure that the DbContext doesn't have to query the database again and instead use the Local tracked version of this User object?
You know that because that is guaranteed by the definition of the Find method (which makes it different from FirstOrDefault, SingleOrDefault and similar):
Finds an entity with the given primary key values. If an entity with the given primary key values is being tracked by the context, then it is returned immediately without making a request to the database. Otherwise, a query is made to the database for an entity with the given primary key values and this entity, if found, is attached to the context and returned. If no entity is found, then null is returned.
So as soon as you use one and the same db context instance (which is the case with ASP.Net Core requests and the db context is registered with scoped lifetime), then the Find method will use the tracked object if exists and won't make database calls.

Return Entity Framework objects from WCF

I am working on a WCF service to provide data to multiple mobile clients. Data model is Entity Framework 4.0. Schema is given below.
When i returnt he object of SysUser the result also contains the navigation properties and EntityKey and other EF related stuff. Is it possible that i get the pure object(only the database fields without the relationship etc).
Thanks
Update
the exception occures "Only parameterless constructors and initializers are supported in LINQ to Entities." on followign code:
return (from u in DataSource.SysUsers
where u.UserID == UserID
select new Player(u)
).FirstOrDefault();
You probably want to send DTOs across the wire rather than your EF objects.
You could use something like AutoMapper to populate your DTOs from the EF objects.
I think if you remove the virtual keyword in your SysUser model for the navigation properties, those will not be loaded. Later, if you need to load this properties, you can do it manually as stated here: http://msdn.microsoft.com/en-us/data/jj574232
Now, if you want to make SysUser travel through a WCF service, it is not a good idea. First, your service's client will need a reference to your Models Project... and that doesn't feels right. If you don't reference your Models, you will get a proxy for it, that is more or less the same as Joe R explained about DTOs.
Here is a related answer: https://stackoverflow.com/a/7161377/7720

MVC SPA w/o EF: You must write an attribute 'type'='object' after writing the attribute with local name '__type'

So I have a very normalized model, and I'm trying to create a single page application in MVC4 which wants to use an entity framework object. My problem is I can't manage to create an entity in EF with the kind of complex mapping that I need (I have checked multiple guides, but I can't seem to make one entity from multiple tables that contain different primary keys... I found a solution using updateable views, but that's really just pushing the abstraction down to the db layer).
So I thought I could create a POCO object using an EF query to create the object, then on insert/update/delete I could just take the POCO data and update the underlying 3 tables.
Well I hit a roadblock just trying to tweak an existing working controller to try and learn what's going on.
Let's imagine I have a working SPA controller that looks like this:
public partial class FooController : DbDataController<aspnetEntities>
{
public IQueryable<Foos> GetFoos() { ... }
}
I just change it a bit to return my new POCO data object Bar, which let's imagine has the exact same fields as Foo for the moment:
public partial class FooController : DbDataController<aspnetEntities>
{
public IQueryable<Bars> GetBars() { ... }
}
Over in FooViewModel.js I update the operation name to GetBars, and the type from
var entityType = "Foo:#Models";
to
var entityType = "Bar:#Models";
I hit my operation directly and I get:
OLD
<ArrayOfFoo><Foo><Property>true</Property></Foo></ArrayOfFoo>
NEW
<ArrayOfBar><Bar><Property>true</Property></Bar></ArrayOfBar>
So the controller looks like it's giving me what I expect, but when I try to put the whole thing together the SPA flashes up:
You must write an attribute 'type'='object' after writing the attribute with local name '__type'.
I'm guessing somehow I need to get type data into KO? I'm not sure where that might be however, I've been crawling through the JS for hours, but I'm not even clear on where it's failing. Any input would be greatly appreciated.
The problem you are experiencing is connected to the fact you are using POCO instead of the standard EF. It should be related to the webapi serializer that somehow doesn't recognize the class as serializable. Anyway it is a bug that will be removed in the RC. Give a look to this thread for workarounds:
http://forums.asp.net/t/1773173.aspx/1?You+must+write+an+attribute+type+object+after+writing+the+attribute+with+local+name+__type+

Sending Entity Framework entities over WCF: how to prevent serialization of navigation fields?

I have a problem when sending Entity Framework-generated entities with navigation properties over WCF. I have a Securities database for storing financial data and two tables inside it:
Stock : Id, Symbol, CompanyName, ExchangeName
Option: Id, StockId, OptionType, Strike
I created an Entity Framework model for this database. Then I created WCF service which exposes generated Stock and Option EF entities to the clients.
My generated entity Stock has navigation property EntityCollection<Option> Options.
When trying to return Stock entity from WCF service to the client, I get an SerializationException: WCF cannot serialize Options navigation property because database connection has been already closed.
I can call Options.Load() method when database connection is opened to fill Options property, but what should I do if I don't want to load full object graph for Stock entity?
I've fought with this one for a while.
First, I turned lazy loading off. But I still had problems with cycles in my object graph.
Then, I put [DataContract(IsReference = true)] tags on all of my entities. That worked, but I still had a lot of performance issues do to a denormalized database.
Finally, I broke down and make dtos and I use AutoMapper to populate them.
One of my coworkers told me to do this from the beginning, and I should have just listened to him. Do yourself a favor and don't make the same mistake that I did.
Edit
I forgot to mention that I had issues deserializing entities that has properties of type ICollection<T>. These will deserialize as arrays. Somehow T[] implements ICollection<T> but Add and Remove will throw exceptions. This was another reason to use DTOs.
With EF5, not sure with EF4, this might work. Change the navigation property setter to private.
public class OptionEntity
{
// properties
// navigation
public virtual StockEntity Stock { get; private set; }
}

Save entities received from WCF service

In my application I need to save with NHibernate entities received from WCF service.
Currently I'm using session SaveOrUpdate method for this purpose.
Often we don't need to edit reference properties, so from client I receive object, which has empty collections. But I don't want this empty collection to reflect in database.
Example:
public class Product
{
public virtual string Name {get;set;}
public virtual IList<Stores> Stores {get;set;} <--- Stores is empty, but should not be cleared in databse.
}
Thanks,
Oksana.
As far as I understand it, you want to update certain properties of the object if it already exsits, and no touch others, is that correct?
Well, basically, in such a case what you'd need to do is this:
establish an NHiberate session
based on some ID, load the current state of the object from the database
update those properties you want to update from the entity you've received in your service call
save the modified object back
With this approach, you'll only update those properties you want, and everything else is being left alone.
Does that seem like an approach you can work with?
Marc
I'm not sure to understand the question. If you are new to NHibernate have a look at the documentation with the term cascade. This defines what is persisted when an object containing others has to be saved.