I encapsulate the DbContext class in my DbContextBase class.
And something about delegating problem.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling;
public abstract class DbContextBase : DbContext
{
public Task<int> ExecuteSaveChangesAsync()
{
return this.ExecuteAsync(base.SaveChangesAsync);
}
private Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> taskFunc)
{
return this.retryPolicy.ExecuteAsync(taskFunc);
}
}
the SaveChangesAsync function is the virtual method at the DbContext clsss (EF Core)
public virtual Task<int> SaveChangesAsync(CancellationToken cancellationToken = default (CancellationToken));
I got the error :
Error CS0411 The type arguments for method
'DbContextBase.ExecuteAsync(Func>)' cannot be
inferred from the usage. Try specifying the type arguments explicitly.
I have no idea about it. Anyone help?
usage:
public Task<int> SaveOrUpdateAsync<T>(T entity, Expression<Func<T, bool>> identifierExpression) where T : class
{
EntityEntry<T> entry = this.Entry(entity);
if (entry.State == EntityState.Detached)
this.Set<T>().Add(entity);
if (this.Set<T>().Any(identifierExpression))
{
entry.State = EntityState.Modified;
}
return this.ExecuteSaveChangesAsync();
}
Related
I have just added GraphDiff in an existing Entity Framework solution which is utilizing Moq framework for testing.
All my tests that are using Moq in insert and update methods are now failing since method _context.UpdateGraph throws following exception: System.NullReferenceException: Object reference not set to an instance of an object.
GraphDiff on GitHub
https://github.com/refactorthis/GraphDiff
UpdateGraph extension method:
https://github.com/refactorthis/GraphDiff/blob/develop/GraphDiff/GraphDiff/DbContextExtensions.cs
How should you hookup Moq with GraphDiff?
We had this problem as well. This is how we solved it.
So this is in the IContext interface:
T UpdateGraph<T>(T entity, Expression<Func<IUpdateConfiguration<T>, object>> mapping = null) where T : class, new();
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
DbEntityEntry Entry(object entity);
DbContextConfiguration Configuration { get; }
This is in the base context:
public virtual T UpdateGraph<T>(T entity, Expression<Func<IUpdateConfiguration<T>, object>> mapping = null) where T : class, new()
{
return null;
}
and
private ObjectContext ObjectContext
{
get { return (this as IObjectContextAdapter).ObjectContext; }
}
And this is in the actual concrete context:
public override T UpdateGraph<T>(T entity, Expression<Func<IUpdateConfiguration<T>, object>> mapping = null) // where T : class, new()
{
return DbContextExtensions.UpdateGraph<T>(this, entity, mapping);
}
and
private ObjectContext ObjectContext
{
get { return (this as IObjectContextAdapter).ObjectContext; }
}
Suppose I have an interface for an object that implements IDisposable, such as this one that I use for my Entity Framework DbContext:
public interface IMyContext : IDisposable
{
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbSet Set(Type entityType);
int SaveChanges();
IEnumerable<DbEntityValidationResult> GetValidationErrors();
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity:class;
DbEntityEntry Entry(object entity);
}
If I was to remove the declaration for IDisposable on this interface, like below:
public interface IMyContext // : IDisposable -- Commented out IDisposable
{
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbSet Set(Type entityType);
int SaveChanges();
IEnumerable<DbEntityValidationResult> GetValidationErrors();
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity:class;
DbEntityEntry Entry(object entity);
}
Would Ninject still be able to dispose of my DbContext if I used this interface to resolve it?
IE: Does Ninject check the object that is being resolved to detect IDisposable, even if it is missing on the interface?
So that's how you can verify it for yourself:
public interface IFoo { }
public class Foo : IDisposable
{
public void Dispose()
{
Console.WriteLine("got disposed");
}
}
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>().InSingletonScope();
kernel.Get<IFoo>();
kernel.Dispose();
if you can see "got disposed" .. well.. it got disposed.. if not.. it didn't!
Of course feel free to replace the Console.WriteLine with a static boolean flag or so..
I have been assigned a new project and I have decided to give EF a go.In this project all I do is getting data there is no persistence.I have to implement some caching and that's it.
Reading about Repository patterns I have found tons of code samples etc... they seem all wrong to me.They implement a one to one Entity to Repository.
In my project I just need reading data not saving etc... just reading.I have 100s entities I cannot create 100s repository seems all wrong.
I have decided to start simple and I all need is this:
public interface IRepository : IDisposable
{
IEnumerable<T> GetAll<T>() where T : class;
IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class;
T GetOne<T>(Expression<Func<T, bool>> predicate) where T : class;
}
public class Repository : IRepository
{
public IEnumerable<T> GetAll<T>() where T : class
{
return ???.ToArray();
}
public IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class
{
return ???.Where(predicate).ToArray();
}
public T GetOne<T>(Expression<Func<T, bool>> predicate) where T : class
{
return ???.Where(predicate).FirstOrDefault();
}
public void Dispose()
{
throw new NotImplementedException();
}
}
What I am struggling with is where i put the "???" that should be my IdbSet.
How could I Implement my concrete repository?Any suggestions or noddy test sample will do.
many thanks
First, you better change the GetAll() and Find() methods to return IQueryable<T> instead of IEnumerable<T>, so that further querying on the dataset would be implemented using Linq-to-Entities.
As of the EF implementation, try something like this:
public class EFRepository : DbContext, IRepository
{
// ctor:
// pass a full connecting-string, or "name=someName" from configuration
public EFRepository(string connectionStringOrName) : base(connectionStringOrName)
{
// init sets
this.Entities1 = this.Set<EntityOfSomeType>();
this.Entities2 = this.Set<EntityOfOtherType>();
}
public IEnumerable<T> GetAll<T>() where T : class
{
return this.Set<T>().ToArray();
}
public IEnumerable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class
{
return this.Set<T>().Where(predicate).ToArray();
}
public T GetOne<T>(Expression<Func<T, bool>> predicate) where T : class
{
return this.Set<T>.FirstOrDefault(predicate);
}
public void Dispose()
{
base.Dispose();
}
// Your DbSets...
public IDbSet<EntityOfSomeType> Entities1 { get; set; }
public IDbSet<EntityOfAnotherType> Entities2 { get; set; }
}
(I used DbContext with the assumption that you're going code-first)
So the problem I am trying to solve is this; We are using Entity Framework to access our Oracle database that has 1200-1500 tables. Now mind you we are not accessing them all, but possibly could have 800+ to access. We are using the UnitOfWork --> Repository --> Service pattern and that works great, but we are trying to figure out if we should have one big DbContext, or multiple little contexts that are specific to the task at hand.
Our UnitOfWork is setup using an EFUnitOfWorkBase like so:
public abstract class EFUnitOfWorkBase : IUnitOfWork
{
private bool isDisposed = false;
public DbContextBase Context { get; set; }
protected EFUnitOfWorkBase(DbContextBase context)
{
Context = context;
}
public int Commit()
{
return Context.SaveChanges();
}
public void Dispose()
{
if (!isDisposed)
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
isDisposed = true;
if (disposing)
{
if (this.Context != null)
this.Context.Dispose();
}
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : Common.EntityBase<TEntity>
{
return new Repository<TEntity>(this);
}
}
Any unit of work we create extends that base one and provides the context like so:
public class EmployeeDirectoryUnitOfWork : EFUnitOfWorkBase
{
public EmployeeDirectoryUnitOfWork(string connectionString)
: base(new EmployeeDirectoryContext(connectionString))
{
}
}
The DbContext is passed a connection string through the unit of work.
The Repository looks like this:
public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContextBase Context;
protected DbSet<TEntity> EntitySet;
public RepositoryBase(EFUnitOfWorkBase unitOfWork)
{
Enforce.ArgumentNotNull(unitOfWork, "unitOfWork");
Context = unitOfWork.Context;
EntitySet = Context.Set<TEntity>();
}
public TEntity Add(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Add(entity);
}
public TEntity Attach(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Attach(entity);
}
public TEntity Delete(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Remove(entity);
}
public System.Linq.IQueryable<TEntity> Query()
{
return EntitySet.AsQueryable();
}
public TEntity Save(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
Attach(entity);
Context.MarkModified(entity);
return entity;
}
}
Any suggestions on how to best handle this situation?
In such a case when you have a large application like this, I think you should probably go for a more Domain Driven Design approach and split the contexts into some separate, bounded contexts. This way when later developers are adding features to the program they will be confined to only being able to access certain tables depending on which context they will be using there.
For better information, Julie Lerman recently came out with a course on Pluralsight about Entity Framework in the Enterprise that's really good. She posted a small clip of it (actually about bounded contexts) on this site. It's a very good course, and I highly recommend it, especially for what you appear to be doing.
Doing my first SL4 MVVM RIA based application and i ran into the following situation:
updating a record (EF4,NO-POCOS!!) in the SL-client seems to take place, but values in the dbms are unchanged. Debugging with Fiddler the message on save is (amongst others):
EntityActions.nil� b9http://schemas.microsoft.com/2003/10/Serialization/Arrays^HasMemberChanges�^Id�^ Operation�Update
I assume that this says only: hey! the dbms should do an update on this record, AND nothing more! Is that right?!
I 'm using a generic repository like this:
public class Repository<T> : IRepository<T> where T : class
{
IObjectSet<T> _objectSet;
IObjectContext _objectContext;
public Repository(IObjectContext objectContext)
{
this._objectContext = objectContext;
_objectSet = objectContext.CreateObjectSet<T>();
}
public IQueryable<T> AsQueryable()
{
return _objectSet;
}
public IEnumerable<T> GetAll()
{
return _objectSet.ToList();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> where)
{
return _objectSet.Where(where);
}
public T Single(Expression<Func<T, bool>> where)
{
return _objectSet.Single(where);
}
public T First(Expression<Func<T, bool>> where)
{
return _objectSet.First(where);
}
public void Delete(T entity)
{
_objectSet.DeleteObject(entity);
}
public void Add(T entity)
{
_objectSet.AddObject(entity);
}
public void Attach(T entity)
{
_objectSet.Attach(entity);
}
public void Save()
{
_objectContext.SaveChanges();
}
}
The DomainService Update Method is the following:
[Update]
public void UpdateCulture(Culture currentCulture)
{
if (currentCulture.EntityState == System.Data.EntityState.Detached)
{
this.cultureRepository.Attach(currentCulture);
}
this.cultureRepository.Save();
}
I know that the currentCulture-Entity is detached. What confuses me (amongst other things) is this: is the _objectContext still alive? (which means it "will be"??? aware of the changes made to record, so simply calling Attach() and then Save() should be enough!?!?)
What am i missing?
Development Environment: VS2010RC - Entity Framework 4 (no POCOs)
Thanks in advance
You are attaching the culture in the context, but you are not telling the context that the object has actually changed.
The generated code I have on my machine is:
public void UpdateDepartment(Department currentDepartment) {
if ((currentDepartment.EntityState == EntityState.Detached)) {
this.ObjectContext.AttachAsModified(currentDepartment, this.ChangeSet.GetOriginal(currentDepartment));
}
}
What matters is the 'AttachAsModified'.
Timores pointed me in the correct direction, the solution (as far as my problem concerns) is very simple: simply add this method to the repository and we're done:
public void AttachModified(T entity)
{
_objectSet.Attach(entity);
_context.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
}
Now instead of calling Attach() we call AttachModified().
Thank you Timores!