Entity Framework Code First - No Detach() method on DbContext - entity-framework

I'm wondering why there is no Detach method on the DbContext object like there is for ObjectContext.  I can only assume this omission was intentional, but I have a hard time figuring out why.  I need to be able to detach and re-attach entities (for putting in the cache in an ASP.NET project, for example).  However, since I can't detach an entity, when I try to attach an entity that was associated with a previous context, I get the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" exception.
What's the guidance here?  Am I missing something?

For people that might stumble upon this question, as of CTP5 you now need to write
((IObjectContextAdapter)context).ObjectContext
in order to get to ObjectContext.

DbContext uses an ObjectContext internally and EF team make this available as a protected property just in case you ever need to drop down to the lower level API and sounds like this is the case here, so you can use or expose the required functionality from a derived DbContext:
public class YourContext : DbContext
{
public void Detach(object entity)
{
ObjectContext.Detach(entity);
}
}
Then you can call this method from your controller to detach an entity.
Alternatively, you can change it to even have a richer API:
public class YourContext : DbContext
{
public void ChangeObjectState(object entity, EntityState entityState)
{
ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
}
}
Here is how DbContext looks like from metadata:
public class DbContext : IDisposable
{
protected System.Data.Objects.ObjectContext ObjectContext { get; }
...
}

EF:CF 4.1 RC1 and EF:CF 4.1 RTW have the same explicitly implemented IObjectContextAdapter:
public static class DbContextExtensions
{
public static void Detach(this System.Data.Entity.DbContext context, object entity)
{
((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
}
}
Microsoft decided "Detach is too advanced technology and should be hidden". IMHO the man who invented this should be shot - because if you add brand new entity, it is otherwise difficult to just remove it without commiting changes to db (you can manipulate with DbEntityEntry but that's another story).
Edit 4 years later:
With EF6 (i somehow skipped EF5 :) ) you dont need detach() anymore, becouse removing freshly added entry does not generate delete from [table] where [Id] = 0 as in EF4 - you can just call mySet.Remove(myFreshlyCreatedAndAddedEntity) and everything will be allright.

I usually extend the base class(inherits from the DbContext) with the property:
public class MyDbContext : DbContext
{
public ObjectContext ThisObjectContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
}
later you can use this property for variety of useful stuff ... like Detach :)

Related

Can I keep Entity Framework context as class variable?

I'm used to working the database connections where you connect/open/close as fast as possible in each method. I'm now working with the Entity Framework and so my methods all do this type of thing:
using (var context = new FooEntities()) {
// linq to sql query here
}
I've been told that with Entity Framework I can actually have that context variable be a class level variable and not have to instantiate it in each method. Is that really the case, or should I continue this pattern in each method?
I'm using version 5.0.0 of the framework if that makes a difference.
It depends on how you are expecting it to act. The only reason you'd want it to stick around is if you wanted to use the caching feature of DbContext across multiple method calls. But since its pulling connections from the Pool anyway, disposing of a DbContext shouldn't really impact performance when creating a new one.
For me personally, I create the context as close as possible and kill it as soon as possible. Thus, the Get calls should use AsNoTracking() to speed up the calls a lot if you don't care about trying to update them later. You could also create a DbContextFactory so each class could control that interaction as it sees fit. (i.e. Method A always creates a new one, but Methods B and C could share if either one called first). Though, that could cause its own issues down the road, but then you can opt into those conditions.
You can have Context as a property of a class, but you have to consider how to control the disposing of the Context. For example:
public class UnitOfWork:IDisposable
{
public DbContext Context { get; set; }
public UnitOfWork()
{
Context = null; //initialize context here
}
public void DoWorkWithContext1()
{
//anything you need
}
public void DoWorkWithContext2()
{
//anything you need
}
public void Dispose()
{
if (Context != null)
Context.Dispose();
}
}
Then you'll use the class in this way:
using (var unit= new UnitOfWork())
{
unit.DoWorkWithContext1();
unit.DoWorkWithContext2();
}

Generic repository implementation with EF

For a simple repository
public interface ISimpleRepository<T>
{
IApplicationState AppState { get; set; }
void Add(T instance);
void Delete(T instance);
void Delete(Guid rowGuid);
IQueryable<T> GetAll();
T Load(Guid rowGuid);
void SaveChanges();
void Update(T instance);
}
my implementation of the Load() method for specific repository for class Product might look like this:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
Now this is assumed when my repository implementation class looks like this:
public class EntityFrameworkProductsProvider : IRepository<Product> ...
What if I had like dozens or hundreds of this small and simple entities that would all use the same behaviour when doing CRUDs (use the same implementation of methods)? I certainly don't want to go and create a class to implement IRepository for each one of them..
I want something like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
but I don't know how to implement the LINQ Select expression then because of course I can't write from e in _ctx.T where e... or do I?
I haven't run into this scenario yet because so far I only had very specific entities with custom repository implementation.
Because you tagged your question with entity-framework and entity-framework-4 I assume you are using ObjectContext API. ObjectContext offers method CreateObjectSet<T> which is equivalent of Set<T> on DbContext.
This question is actually duplicate of either:
Generic GetById with DbContext
Generic GetById with ObjectContext
Instead of writing _ctx.Products, you can write _ctx.Set<T>. That takes care of half of the problem (you need to add a generic constraint where T: class to your repository)
Then, if rowid is the object's key, you can use _ctx.Set<T>.Find(rowid) instead of a LINQ query to retrieve by Id.
Alternatively, you can create a base interface IHaveId (or a BaseEntity class, whatever you like) which has the Id property, and then add that as an generic constraint on T, so you can use it in your queries.
If you're using EF 4.1, see the sample generic repository here:
http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
I know that this is possible in EF4.1 with the DbContext API, where you have a "Set" method on the context that gets you the entity set corresponding to the type T. this way, you could have your repository like this:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
one more remark: I think you could use this syntax :
return _ctx.Products.FirstOrDefault(c=>c.id == rowid);
to get the entity you want instead of using the (from... in...). it's clearer (in my opinion) :)
Hope this helps

Entity Framework 4, MOQ,

I am using EF4, Microsoft.Entity.CTP, and the latest MOQ. I am trying to create a generic repository class and moq the DBContext using MOQ. Whenever I run my moq test I get "object reference not set to an instance of an object" on this.context.Set().Add(entity); and I don't understand why. The code runs ok without a moq.
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
private IContext context;
public GenericRepository(IContext context)
{
this.context = context;
}
public IList<TEntity> List
{
get { return context.Set<TEntity>().ToList(); }
}
public void Create(TEntity entity)
{
this.context.Set<TEntity>().Add(entity);
this.context.SaveChanges();
}
}
var mock = new Mock<IContext>();
GenericRepository<Product> producRepository = new GenericRepository<Product>(mock.Object);
mock.Setup(x => x.Product.Add(productType));
mock.Setup(x => x.SaveChanges());
productRepository.Create(product);
mock.VerifyAll();
You need to mock out the list implementation behind Set. I'm not at the compute ATM but iirc it's an IDbSet.
Change your code first definitions from DbSet to IDbSet and then you can mock them.
http://blogs.msdn.com/b/efdesign/archive/2010/06/21/productivity-improvements-for-the-entity-framework.aspx
I am considering changing my DbContext.tt file to generate IDbSet instead of DbSet, but only after I get the mocking to work.
I am not saying this makes the rest of the work easy, but it will get you past one problem.
What I need help with is what to do after changing my code first definitions to be based on the EF DbContext interfaces. For example, I create instances of my DbSet objects and add them.
Mock<IPosManContext> posManContext;
posManContext.Object.Set(typeof(note_template));
posManContext.Object.note_template.Add(
new note_template()
{
note_template_id = 1,
act_flag = "Y",
desc_text = "Monday Monday",
last_update_dtm = now,
last_update_user_id = "hsimpson",
});
But I get an error that the DbSet is null.
Microsoft needs to provide a good example of what to do.
They went half the way by providing public interfaces for mocking, but I still need more help.
Joe

WCF with Entity Framework Error

Error: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I am trying to create a WCF service with Entity Framework (VS 2010, .NET 4). When I run it, I get the above error.
I read something about editing the T4 template, but it appears that it already has
[DataContractAttribute(IsReference=true)]
public partial class Person : EntityObject
and
[DataMemberAttribute()]
public global::System.Int32 ID
{
get
{
return _ID;
}
I am not sure what the difference is between
[DataMemberAttribute()] and [DataMember]
or
[DataContractAttribute(IsReference=true)] and [DataContract]
either.
public Person GetPersonByID(int id)
{
using (var ctx = new MyEntities())
{
return (from p in ctx.Person
where p.ID == id
select p).FirstOrDefault();
}
}
How does WCF and EF work together, properly?
Do you have navigation properties in your Person class? Did you disable lazy loading? Otherwise it will probably try to load content for navigation properties during serialization and it fails because of closed context.
To your other questions:
[DataMemberAttribute()] and [DataMember] are same. It is just shorter name.
[DataContractAttribute(IsReference=true)] and [DataContract] are not same. IsRefrence allows tracking circular references in navigation properties. Without this parameter circular reference causes never ending recursion.

Function Import and Repository pattern with Entity Framework 4.0

Could anyone advise me on how they've implemented the use of Function Imports when using the Repository pattern against EF 4.0?
We have a table mapped to a Candidate Entity and also a Function Import off an existing sproc that maps to Candidate. This works great in EF but we're abstracting by use of Repositories which take on their constructor the IObjectSet where T is the POCO entity. However this means I'm unable to get a reference to the function import. The only way I can see of doing this is passing a reference to the ObjectContext to the repositories that need it but this feels like a bit of a design smell to me.
Even though several of our Repositories are extended with custom interfaces we're still faced with the same issue.
public class CandidateRepository : Repository<Candidate>, ICandidateRepository
{
public CandidateRepository(IObjectSet<Candidate> entities)
: base(entities)
{
}
public Candidate GetByEmail(string email)
{
return Entities.SingleOrDefault(c => c.EmailAddress.Equals(email));
}
public bool CandidateExists(string candidateNumber)
{
return Entities.SingleOrDefault(c => c.Number.Equals(candidateNumber)) != null;
}
public Candidate GetByNumber(string number)
{
return Entities.SingleOrDefault(c => c.Number.Equals(number));
}
public Candidate GetMember(string number)
{
return new Candidate(); //This one needs to return from the Function Import
}
}
Any advice greatly appreciated.
To solve your problem directly you can cast entities to ObjectSet<T> and use entites.Context property to get ObjectContext.
public Candidate GetMember(string number)
{
var objectSet = Enities as ObjectSet<Candidate>;
if(objectSet == null) throw new Exception("Oh, it's not EF IObjectSet implementation");
return objectSet.Context.MyCustomFunction(string number);
}
As you can see this code relies on specific IObjectSet implementation which is not good at all.
The better idea is to create repositories for aggregate roots only rather then for each table. So it will be more natural to pass ObjectContext to repository ctor.
I have went down this route and i have experienced that it is less of a pain when you pass in an interface implementation of the ObjectContext to your repository. The interface implementation should have some way of calling the function. So when you pass in the concrete implementation of the ObjectContext everything should work fine.