I'm getting data for my application through WCF service. And on the server side the service is using EF4.1 as a data access.
Service method looks kind of like this :
public List<JobOffer> GetAllJobOffers()
{
var allJobOffers = _jobOffersRepository.GetAll().ToList();
return allJobOffers;
}
And the repository is done this way
public override IQueryable<JobOffer>GetAll()
{
return _context.JobOffers.Include(c => c.Company);
}
I am getting this strange error :
An error occurred while receiving the HTTP response to http://localhost:8080/JobsService/ws. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
In debug mode after hitting F5 it starts to loop forever.
In my case it should some problem with lazy loading on the server side. Because when I am calling the service to return objects with simple structure it works like a champ. What could be messed up? And what is the best practice to eager load objects with EF ?
When using EF over WCF lazy loading should be turned off because serialization will trigger lazy loading of every navigation property. Another problem are cyclic references which are not serializable by default. If your Company has also navigation property to its Jobs it makes cyclic reference.
I think your problem is more like to be related to the cyclic relationship. this all happens when serialization comes in scope. lets say u have e entity person which has property addresses which is marked as lazy. on the other side of relationship Addresses entity has a navigation property for Person entity. as serialization takes place it goes through each property of the person entity and as it access Addresses navigation property starts to load it. now it starts to serialize Address entity and as it access Person navigation property it goes back to that property and starts to serialize it and it creates situation when cyclic serialization starts and can not be completed. to overcome this problem u do not have to turn of lazy loading but all u have to do is to decorate you datacontract in (in this case Person and Addresse) with [DataContract(IsReference = true)] and everything works like an charm.
I know this is a bit of an old question, but based on your experiences in your question, I think it might help if you take a look through one of my recent posts
http://sanderstechnology.com/2013/more-with-the-entity-framework-v6-rc1/12423/
I walk through how to send a semi-complex EF object graph which is deserialized through WCF, and I handle lazy loading, proxy generation and cyclic reference issues. It might be worth a look.
Related
So I have a fairly comprehensive activity-based access control system I built for a web app under MVC 4 using Entity Framework. Well, to be precise the access control doesn't care if it's using EF or not, but the app is.
Anyway, I'm loading the user's permissions on each request right now. I get a reference to my DbContext injected from the IoC container into my ApplicationController, and it overrides OnAuthorization to stuff the user's profile into the HttpContext.Current.Items. Seems to work fairly well, but I can't help but wonder if it's the best way.
My thought was that since the users' permissions don't change often, if ever, the better way to do it would be to load the profile of permissions into the Session instead, and then not have to change them at all until the user logs out and logs back in (pretty common in desktop OS's anyway). But I'm concerned that if I fetch using the DbContext, then the object I get back is a dynamic proxy which holds a reference to the DbContext and I certainly don't want to do that for the whole session.
Thoughts? Is this a good approach, and if so how do I ensure that my DbContext doesn't linger beyond when I really need it?
Invoke .AsNoTracking() on the Set<UserPermission> before you query out. Entities will still be proxied, but will be detached from the DbContext.
var userPermission = dbContext.Set<UserPermission>().AsNoTracking()
.SingleOrDefault(x => x.UserName == User.Identity.Name);
Thoughts? Is this a good approach?
Putting a dynamically proxied entity in session will break as soon as you load balance your code across more than 1 web server. Why? Because of the dynamic proxy class. Server A understands the type DynamicProxies.UserPermission_Guid, because it queried out the entity. However Server B through N do not, and therefore cannot deserialize it from the Session. The other servers will dynamically proxy the entity with a different GUID.
That said, you could DTO your data into a POCO object and put it in session instead. However then you do not need to worry about your entity being attached to the context when you first query it out. AsNoTracking will only make the query perform a bit faster.
// you can still call .AsNoTracking for performance reasons
var userPermissionEntity = dbContext.Set<UserPermission>().AsNoTracking()
.SingleOrDefault(x => x.UserName == User.Identity.Name);
// this can safely be put into session and restored by any server with a
// reference to the DLL where the DTO class is defined.
var userPermissionSession = new UserPermissionInSession
{
UserName = userPermissionEntity.UserName,
// etc.
};
Thoughts? Is this a good approach?
Another problem attached to this approach is when you use the common pattern that create one dbContext per http request. This pattern typically dispose dbContext when the request ends.
protected virtual void Application_EndRequest(object sender, EventArgs e)
But what happen when we try to get navigation property of a proxy entity which reference to a disposed DbContext?
We will get a ObjectDisposedException
Here is the scenario. I have a WCF service, when this service is called it passes control to an instance of another class (created via Ninject). In that class I need to do some work, specifically with Entity Framework and repositories. To cut a long story short, I have the following binding declared.
Bind<IGenericProductRepository>()
.To<GenericProductRepository>()
.WithConstructorArgument( "context", new StagingDataContext());
When I want to use this repository I have the following.
using (var genericProductRepository = IoC.Resolve<IGenericProductRepository>())
The problem is, that I only get a new instance of genericProductRepository if it's a brand new request, if the method is called multiple times in the same request I get an error stating that the context (the EF context) is already disposed, this is because it seems like I am getting the same instance back that was already disposed in the using statement. To explain it another way, using the Microsoft WCF Test Client, if I invoke it the first time, the code runs fine, if I push the invoke button again (without restarting the test client, i.e. the same request) then it throws this error about it being disposed already.
I have tried to play around with the various "scopes" that come with Ninject, but clearly I am missing something.
So my basic question is, how do I get a new repository whenever it hits that line, instead of using the same one ? Help would be greatly appreciated, I'm really trying to push for my company to adopt Ninject and drop Spring.
Look at your binding again. Even without any knowledge about Ninject you should notice that the instance of your context is created exactly once at the time the binding is defined. But what you want is have a new context on every resolve. Best it is done by not using WithConstructorArgument and let Ninject create the instance. Therefore you have to define a additional binding for the type of context. If this is not possible for some reason you have to use the lazy version of WithConstructorArgument
WithConstructorArgument("context", ctx => new StagingDataContext())
Furthermore, you might want to try The WCF extension for Ninject:
https://github.com/ninject/ninject.extensions.wcf
That way you can get rid of the ServiceLocator like usage.
I am trying to implement Code First (CTP 5) in my WCF Data Service (OData). Its a simple scenario, but I get a HTTP 500 Internal Server Error with no much details. I put this on Data Service to show fault error details.
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
However I still don't see what is going wrong.
In Constructor of my DbContext implementation I am calling base class with Connection string like below.
public MyContext() : base("MyConnection")
{
}
And I have a simple member in it like this.
public DbSet<MyData> MyData{ get; set; }
I implemented the members of MyData class as needed.
All I get in browser is 500 Internal server error without any further details.
What could wrong with my implementation?
After some research, trial and error I found the issue. Putting it here to help others landing in this situation. One of the objects in my Model is being treated as a Complex Type and I am referring to it in another POCO object in my Model as a Collection, which apparently is not supported by EF Code First (which makes sense). This links helped me understand it better.
[Complex Types]
http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx
[Conventions in CodeFirst]http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx
Please be aware that there could be many such instances of 500 which is causd due to improper modellign of Objects. Make sure to verify the Conventions and how Code First works in background to understand thee relationships.
I have a WCF service that calls the following method in one of my Repository objects to create a new sale object in the database
public static Sale New(Sale sale)
{
using (var ctx = new DBcontext())
{
ctx.Sales.AddObject(sale);
ctx.SaveChanges();
return sale;
}
}
The WCF method calling this looks like this
public Sale SaleNew(Sale sale)
{
return SaleRepository.New(sale);
}
When I call this from a client application I get the following error
"The underlying connection was closed: The connection was closed unexpectedly."
If I step through all the code seems to run fine and the record gets insterted into the database. If I add the following line to my repository method after the SaveChanges it works fine
ctx.Detach(sale);
Is the exception happening because I'm disposing the context as soon as the method returns? Is using the entity context in this way bad practise ie disposing of it straight away? I'm only doing this because its SOA and pretty much stateless so all my repository methods create the context return the value and dispose the context. Anything that is passed in will either get added to the context or re-attached.
As advised I turned on tracing in WCF and watched what was happening. There was a proxy exception occurring. In this case as I'm using my own POCO objects I don't really want proxy objects so I set the ContextOptions.ProxyCreationEnabled property in my DatabaseContext to false and it now works fine.
1) Is using the entity context in this way bad practise ie disposing of it straight away?
No, that's how I do it - and I believe it is the proper way of doing it. But creating context can be expensive and with EF we are stuck with no ideal way of reusing the context.
2) ctx.Detach(sale);
This as far as I know should not be required for what you are doing although I have had loads of issues with attaching and detaching when I reuse the same entities. This should be only needed if you need to re-attach to context. Are you using Lazy-Loading?
If a project has used POCO for entities and uses entity framework and uses lazy loading then you have an "incomplete" object graph going back over the wire. So when a client uses the Entity is there some sort of proxy that will automagically load the remaining values? Do we have to create this proxy ourselves and wrap the original entity in it? Or is there an accepted pattern for identifying lazy loaded types which would then signal the client to make another call to the WCF?
Lazy loading with WCF usually doesn't work because your method looks like:
public List<MyPoco> GetData()
{
using (var context = new MyObjectContext())
{
return context.MyPocos.ToList();
}
}
As you see context is closed in method (you have to close context somewhere). But when the list is serialized it will try to lazy load dependent objects => exception because context is already closed. In WCF you should use eager loading.
Use flat DTO's, you probably don't want to expose your full domain to the client anyway. WCF is message-based, not Domain Driven.