Generic save method - asp.net-mvc

In my generic repository I need to write generic Save method which will edit existed or add new entity depending on id.
public void Save<T>(T entity) where T : TEntity, IKeyId
{
if (ObjectSet.Any(r => (r as IKeyId).KeyId == entity.KeyId))
{
Edit(entity);
}
else
{
Add(entity);
}
}
But Linq generate exception when I try do Any( r=> (r as IKeyId)....
The 'TypeAs' expression with an input of type 'MyProg.DAL.Appeal' and a check of type 'Claimstrak.DAL.Interfaces.IKeyId' is not supported. Only entity types and complex types are supported in LINQ to Entities queries.
How to write it correct?

Well, the truth is that you dont need to use the ObjectSet, you can just use DbContext to do this, in a much more easy way.
Bu, i would tell that this is not a good pattern to use, to call a Save() in a repository. I would recomend that you consider the .SaveSession() of the Context only after all was done, this way you can do a lot of things befose making a round trip to te database.
So, you should make a method like this, but not call the SaveChanges(), instead of a Save() method, to a UpdateOrInsert() and them, after all is done you call the .Save()
But i will give the examplefollowing your request (but i dont recommend, i recommend you separate IUnitOfWork from IRepository)
See how the code is very simple:
interface IKeyId
{
int Id { get; set; }
}
DbContext context = new YourContext();
public bool Save<TEntity>(TEntity entity) where TEntity : class, IKeyId
{
return (entity.Id == 0) ? Add<TEntity>(entity) : Edit<TEntity>(entity);
}
public bool Edit<TEntity>(TEntity entity) where TEntity : class, IKeyId
{
var set = context.Set<TEntity>();
set.Attach(entity);
return true;
}
public bool Add<TEntity>(TEntity entity) where TEntity : class, IKeyId
{
var set = context.Set<TEntity>();
set.Add(entity);
return true;
}
I use a similar approach im my repositories, i have changed the T4 (.tt file) that generates the POCO classes from my database to excplicitly implement some interfaces that i have, such as IAuditable, IValidatable and other, so the T4 automaticaly implement those interfaces in the classes.

Related

Automapper + EF4 + ASP.NET MVC - getting 'context disposed' error (I know why, but how to fix it?)

I have this really basic code in a MVC controller action. It maps an Operation model class to a very basic OperationVM view-model class .
public class OperationVM: Operation
{
public CategoryVM CategoryVM { get; set; }
}
I need to load the complete list of categories in order to create a CategoryVM instance.
Here's how I (try to) create a List<OperationVM> to show in the view.
public class OperationsController : Controller {
private SomeContext context = new SomeContext ();
public ViewResult Index()
{
var ops = context.Operations.Include("blah...").ToList();
Mapper.CreateMap<Operation, OperationVM>()
.ForMember(
dest => dest.CategoryVM,
opt => opt.MapFrom(
src => CreateCatVM(src.Category, context.Categories)
// trouble here ----------------^^^^^^^
)
);
var opVMs = ops.Select(op => Mapper.Map<Operation, OperationVM>(op))
.ToList();
return View(opVMs);
}
}
All works great first time I hit the page. The problem is, the mapper object is static. So when calling Mapper.CreateMap(), the instance of the current DbContext is saved in the closure given to CreateMap().
The 2nd time I hit the page, the static map is already in place, still using the reference to the initial, now disposed, DbContext.
The exact error is:
The operation cannot be completed because the DbContext has been disposed.
The question is: How can I make AutoMapper always use the current context instead of the initial one?
Is there a way to use an "instance" of automapper instead of the static Mapper class?
If this is possible, is it recommended to re-create the mapping every time? I'm worried about reflection slow-downs.
I read a bit about custom resolvers, but I get a similar problem - How do I get the custom resolver to use the current context?
It is possible, but the setup is a bit complicated. I use this in my projects with help of Ninject for dependency injection.
AutoMapper has concept of TypeConverters. Converters provide a way to implement complex operations required to convert certain types in a separate class. If converting Category to CategoryVM requires a database lookup you can implement that logic in custom TypeConverter class similar to this:
using System;
using AutoMapper;
public class CategoryToCategoryVMConverter :
TypeConverter<Category, CategoryVM>
{
public CategoryToCategoryVMConverter(DbContext context)
{
this.Context = context;
}
private DbContext Context { get; set; }
protected override CategoryVM ConvertCore(Category source)
{
// use this.Context to lookup whatever you need
return CreateCatVM(source, this.Context.Categories);
}
}
You then to configure AutoMapper to use your converter:
Mapper.CreateMap<Category, CategoryVM>().ConvertUsing<CategoryToCategoryVMConverter>();
Here comes the tricky part. AutoMapper will need to create a new instance of our converter every time you map values, and it will need to provide DbContext instance for constructor. In my projects I use Ninject for dependency injection, and it is configured to use the same instance of DbContext while processing a request. This way the same instance of DbContext is injected both in your controller and in your AutoMapper converter. The trivial Ninject configuration would look like this:
Bind<DbContext>().To<SomeContext>().InRequestScope();
You can of course use some sort of factory pattern to get instance of DbContext instead of injecting it in constructors.
Let me know if you have any questions.
I've found a workaround that's not completely hacky.
Basically, I tell AutoMapper to ignore the tricky field and I update it myself.
The updated controller looks like this:
public class OperationsController : Controller {
private SomeContext context = new SomeContext ();
public ViewResult Index()
{
var ops = context.Operations.Include("blah...").ToList();
Mapper.CreateMap<Operation, OperationVM>()
.ForMember(dest => dest.CategoryVM, opt => opt.Ignore());
var opVMs = ops.Select(
op => {
var opVM = Mapper.Map<Operation, OperationVM>(op);
opVM.CategoryVM = CreateCatVM(op.Category, context.Categories);
return opVM;
})
.ToList();
return View(opVMs);
}
}
Still curious how this could be done from within AutoMapper...
The answer from #LeffeBrune is perfect. However, I want to have the same behavior, but I don't want to map every property myself. Basically I just wanted to override the "ConstructUsing".
Here is what I came up with.
public static class AutoMapperExtension
{
public static void ConstructUsingService<TSource, TDestination>(this IMappingExpression<TSource, TDestination> mappingExression, Type typeConverterType)
{
mappingExression.ConstructUsing((ResolutionContext ctx) =>
{
var constructor = (IConstructorWithService<TSource, TDestination>)ctx.Options.ServiceCtor.Invoke(typeConverterType);
return constructor.Construct((TSource)ctx.SourceValue);
});
}
}
public class CategoryToCategoryVMConstructor : IConstructorWithService<Category, CategoryVM>
{
private DbContext dbContext;
public DTOSiteToHBTISiteConverter(DbContext dbContext)
{
this.dbContext = dbContext;
}
public CategoryVM Construct(Category category)
{
// Some commands here
if (category.Id > 0)
{
var vmCategory = dbContext.Categories.FirstOrDefault(m => m.Id == category.Id);
if (vmCategory == null)
{
throw new NotAllowedException();
}
return vmCategory;
}
return new CategoryVM();
}
}
// Initialization
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => nInjectKernelForInstance.Get(type));
cfg.CreateMap<Category, CategoryVM>().ConstructUsingService(typeof(CategoryToCategoryVMConstructor));
};

Entity Framework 4 - Generic method for retrieving entity by ID

I am writing method for fetching single entities by their ID :
public Customer GetCustomer(int i_CustomerID)
{
return (from c in context.CustomerSet
where c.Id == i_CustomerID
select c).SingleOrDefault();
}
public Movie GetMovie(int i_MovieID)
{
return (from m in context.MovieSet
where m.Id == i_MovieID
select m).SingleOrDefault();
}
But I have many entities and this code repeats itself. I want to write a method like this:
public T GetEntityByID<T>(int i_EntityID)
{
return (from e in context.T_Set
where e.Id == i_EntityID
select e).SingleOrDefault();
}
Is there a way to achieve that ?
I haven't actually executed this but it compiles and is probably something along the lines of what you are trying to achieve:
public static void Testing()
{
SelectEntity<MyObject>(r => r.MyObjectId == 1);
}
public static T SelectEntity<T>(Expression<Func<T, bool>> expression) where T : EntityObject
{
MyContext db = new MyContext();
return db.CreateObjectSet<T>().SingleOrDefault(expression);
}
The problem is that there is no common super type that has the relevant properties that you seek. It is easy, however, to code generate your fetch methods using the in-built T4 code generation tool that EF is using. Here is a good link on how to hook in and generate the sort of code you need.
http://msdn.microsoft.com/en-us/data/gg558520
If you know that your generic repository will be always used with entity types which have PK with the same name and the same type you can simply define interface like this:
public interface IEntity
{
int Id { get; }
}
and either implement this interface in partial part of your generated entities or modify T4 template to include it automatically. Your repository will be then defined as:
public interface IRepository<TEntity> where T : IEntity
{
...
}
If the type of PK can change but the name is still the same you can improve the entity interface to:
public interface IEntity<TKey>
{
TKey Id { get; set; }
}
and the definition of repository will be:
public interface IRepository<TEntity, TKey> where TEntity : IEntity<TKey>
{
...
}
If you want generic repository which is able to work with entities with different PK's name and type check this answer. That solution should probably also work (or with small modification) with composite PKs.

Mocking DbContext.Set<T>()?

We're using EF Code first, and have a data context for our sales database. Additionally, we have a class that sits on top of our data context and does some basic CRUD operations.
For example, we have the following function:
public static T Create<T>(int userId, T entity) where T : class, IAllowCreate
{
if (entity == null)
throw new ArgumentNullException("entity");
using (SalesContext dc = new SalesContext())
{
dc.Set<T>().Add(entity);
dc.SaveChanges();
return entity;
}
}
I found an example of how to create fake contexts and IDBset properties. I started implementing that, but I ran in to an issue.
We use dc.Set() quite liberally (as seen above) in our code, as we attempt to create generic CRUD methods. Instead of having a ReadCustomer, ReadContact etc, we would just do Read(). However, dc.Set returns a DbSet, not an IDbSet, so I'm not able to mock that.
Has anyone been able to mock or fake DbContext and still use the Set functionality?
interface ISalesContext
{
IDbSet<T> GetIDbSet<T>();
}
class SalesContext : DbContext, ISalesContext
{
public IDbSet<T> GetIDbSet<T>()
{
return Set<T>();
}
}
I used a different name, but you can use the new operator if you prefer to hide the regular implementation.

What type of dependency to inject?

I have a specification that validates codes. It looks like the following:
public ClassificationSpecification : ISpecification<Classification> {
HashSet<string> codes;
// constructor elided
public IsSatisfiedBy(Classification classification) {
return codes.Contains(classification.Code);
}
}
The valid codes come out of a Classification table in a database. My question is, which is the better constructor for dependency injection?
public CodeSpecification(IEnumerable<string> codes) {
this.codes = new HashSet<string>(codes);
}
or
public CodeSpecification(IRepository<Classification> repository) {
this.codes = new HashSet<string>(repository.Select(x => x.Code));
}
And the all important question: why?
Your second constructor does real work (via the repository) and this is a bad idea. See http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/
You need to decide if it's valid to load all the values (pass in the values you need to the constructor), or you want to look them up on each call (pass in the repository in the constructor and store it).
I would use this constructor:
private readonly IRepository<Classification> _repository;
public CodeSpecification(IRepository<Classification> repository)
{
_repository = repository;
}
Then, find the valid codes when your class is actually called upon:
public bool IsSatisfiedBy(Classification classification)
{
var _repository.Any(x => x.Code == classification.Code);
}
This ensures that no real work is done until it is needed, separating your application's initialization from its runtime. It also ensures that you are always working with fresh data in IsSatisfiedBy; caching the values in the constructor introduces a period of time where the codes in the repository might change.
If the number of codes is large, and the repository won't execute the Any efficiently, you may still want to implement caching. It is a good idea to follow the same advice and not cache until the first call to IsSatisfiedBy:
private readonly HashSet<string> _codes;
private readonly object _codesSync = new object();
public bool IsSatisfiedBy(Classification classification)
{
if(_codes == null)
{
lock(_codesSync)
{
if(_codes == null)
{
_codes = new HashSet<string>(_repository.Select(x => x.Code));
}
}
}
return _codes.Contains(classification.Code);
}
Constructors in dependency-injected objects are infrastructure elements; domain logic of any kind should generally be deferred until the object is invoked by another.

How to remove unit of work functionality from repositories using IOC

I have an application using ASP.NET MVC, Unity, and Linq to SQL.
The unity container registers the type AcmeDataContext which inherits from System.Data.Linq.DataContext, with a LifetimeManager using HttpContext.
There is a controller factory which gets the controller instances using the unity container. I set-up all my dependencies on the constructors, like this:
// Initialize a new instance of the EmployeeController class
public EmployeeController(IEmployeeService service)
// Initializes a new instance of the EmployeeService class
public EmployeeService(IEmployeeRepository repository) : IEmployeeService
// Initialize a new instance of the EmployeeRepository class
public EmployeeRepository(AcmeDataContext dataContext) : IEmployeeRepository
Whenever a constructor is needed, the unity container resolves a connection, which is used to resolve a data context, then a repository, then a service, and finally the controller.
The issue is that IEmployeeRepository exposes the SubmitChanges method, since the service classes DO NOT have a DataContext reference.
I have been told that the unit of work should be managed from outside the repositories, so it would seem I ought to remove SubmitChanges from my repositories. Why is that?
If this is true, does this mean that I have to declare an IUnitOfWork interface and make every service class dependent upon it? How else can I allow my service classes to manage the unit of work?
You shouldn't try to supply the AcmeDataContext itself to the EmployeeRepository. I would even turn the whole thing around:
Define a factory that allows creating a new unit of work for the Acme domain:
Create an abstract AcmeUnitOfWork that abstracts away LINQ to SQL.
Create a concrete factory that can allows creating new LINQ to SQL unit of works.
Register that concrete factory in your DI configuration.
Implement an InMemoryAcmeUnitOfWork for unit testing.
Optionally implement convenient extension methods for common operations on your IQueryable<T> repositories.
UPDATE: I wrote a blog post on this subject: Faking your LINQ provider.
Below is a step-by-step with examples:
WARNING: This will be a loooong post.
Step 1: Defining the factory:
public interface IAcmeUnitOfWorkFactory
{
AcmeUnitOfWork CreateNew();
}
Creating a factory is important, because the DataContext implement IDisposable so you want to have ownership over the instance. While some frameworks allow you to dispose objects when not needed anymore, factories make this very explicit.
Step 2: Creating an abstract unit of work for the Acme domain:
public abstract class AcmeUnitOfWork : IDisposable
{
public IQueryable<Employee> Employees
{
[DebuggerStepThrough]
get { return this.GetRepository<Employee>(); }
}
public IQueryable<Order> Orders
{
[DebuggerStepThrough]
get { return this.GetRepository<Order>(); }
}
public abstract void Insert(object entity);
public abstract void Delete(object entity);
public abstract void SubmitChanges();
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract IQueryable<T> GetRepository<T>()
where T : class;
protected virtual void Dispose(bool disposing) { }
}
There are some interesting things to note about this abstract class. The Unit of Work controls and creates the Repositories. A repository is basically something that implements IQueryable<T>. The repository implements properties that return a specific repository. This prevents users from calling uow.GetRepository<Employee>() and this creates a model that is very close to what you are already doing with LINQ to SQL or Entity Framework.
The unit of work implements Insert and Delete operations. In LINQ to SQL these operations are placed on the Table<T> classes, but when you try to implement it this way it will prevent you from abstracting LINQ to SQL away.
Step 3. Create a concrete factory:
public class LinqToSqlAcmeUnitOfWorkFactory : IAcmeUnitOfWorkFactory
{
private static readonly MappingSource Mapping =
new AttributeMappingSource();
public string AcmeConnectionString { get; set; }
public AcmeUnitOfWork CreateNew()
{
var context = new DataContext(this.AcmeConnectionString, Mapping);
return new LinqToSqlAcmeUnitOfWork(context);
}
}
The factory created a LinqToSqlAcmeUnitOfWork based on the AcmeUnitOfWork base class:
internal sealed class LinqToSqlAcmeUnitOfWork : AcmeUnitOfWork
{
private readonly DataContext db;
public LinqToSqlAcmeUnitOfWork(DataContext db) { this.db = db; }
public override void Insert(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.db.GetTable(entity.GetType()).InsertOnSubmit(entity);
}
public override void Delete(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
this.db.GetTable(entity.GetType()).DeleteOnSubmit(entity);
}
public override void SubmitChanges();
{
this.db.SubmitChanges();
}
protected override IQueryable<TEntity> GetRepository<TEntity>()
where TEntity : class
{
return this.db.GetTable<TEntity>();
}
protected override void Dispose(bool disposing) { this.db.Dispose(); }
}
Step 4: Register that concrete factory in your DI configuration.
You know self best how to register the IAcmeUnitOfWorkFactory interface to return an instance of the LinqToSqlAcmeUnitOfWorkFactory, but it would look something like this:
container.RegisterSingle<IAcmeUnitOfWorkFactory>(
new LinqToSqlAcmeUnitOfWorkFactory()
{
AcmeConnectionString =
AppSettings.ConnectionStrings["ACME"].ConnectionString
});
Now you can change the dependencies on the EmployeeService to use the IAcmeUnitOfWorkFactory:
public class EmployeeService : IEmployeeService
{
public EmployeeService(IAcmeUnitOfWorkFactory contextFactory) { ... }
public Employee[] GetAll()
{
using (var context = this.contextFactory.CreateNew())
{
// This just works like a real L2S DataObject.
return context.Employees.ToArray();
}
}
}
Note that you could even remove the IEmployeeService interface and let the controller use the EmployeeService directly. You don't need this interface for unit testing, because you can replace the unit of work during testing preventing the EmployeeService from accessing the database. This will probably also save you a lot of DI configuration, because most DI frameworks know how to instantiate a concrete class.
Step 5: Implement an InMemoryAcmeUnitOfWork for unit testing.
All these abstractions are there for a reason. Unit testing. Now let's create a AcmeUnitOfWork for unit testing purposes:
public class InMemoryAcmeUnitOfWork: AcmeUnitOfWork, IAcmeUnitOfWorkFactory
{
private readonly List<object> committed = new List<object>();
private readonly List<object> uncommittedInserts = new List<object>();
private readonly List<object> uncommittedDeletes = new List<object>();
// This is a dirty trick. This UoW is also it's own factory.
// This makes writing unit tests easier.
AcmeUnitOfWork IAcmeUnitOfWorkFactory.CreateNew() { return this; }
// Get a list with all committed objects of the requested type.
public IEnumerable<TEntity> Committed<TEntity>() where TEntity : class
{
return this.committed.OfType<TEntity>();
}
protected override IQueryable<TEntity> GetRepository<TEntity>()
{
// Only return committed objects. Same behavior as L2S and EF.
return this.committed.OfType<TEntity>().AsQueryable();
}
// Directly add an object to the 'database'. Useful during test setup.
public void AddCommitted(object entity)
{
this.committed.Add(entity);
}
public override void Insert(object entity)
{
this.uncommittedInserts.Add(entity);
}
public override void Delete(object entity)
{
if (!this.committed.Contains(entity))
Assert.Fail("Entity does not exist.");
this.uncommittedDeletes.Add(entity);
}
public override void SubmitChanges()
{
this.committed.AddRange(this.uncommittedInserts);
this.uncommittedInserts.Clear();
this.committed.RemoveAll(
e => this.uncommittedDeletes.Contains(e));
this.uncommittedDeletes.Clear();
}
protected override void Dispose(bool disposing)
{
}
}
You can use this class in your unit tests. For instance:
[TestMethod]
public void ControllerTest1()
{
// Arrange
var context = new InMemoryAcmeUnitOfWork();
var controller = new CreateValidController(context);
context.AddCommitted(new Employee()
{
Id = 6,
Name = ".NET Junkie"
});
// Act
controller.DoSomething();
// Assert
Assert.IsTrue(ExpectSomething);
}
private static EmployeeController CreateValidController(
IAcmeUnitOfWorkFactory factory)
{
return new EmployeeController(return new EmployeeService(factory));
}
Step 6: Optionally implement convenient extension methods:
Repositories are expected to have convenient methods such as GetById or GetByLastName. Of course IQueryable<T> is a generic interface and does not contains such methods. We could clutter our code with calls like context.Employees.Single(e => e.Id == employeeId), but that's really ugly. The perfect solution to this problem is: extension methods:
// Place this class in the same namespace as your LINQ to SQL entities.
public static class AcmeRepositoryExtensions
{
public static Employee GetById(this IQueryable<Employee> repository,int id)
{
return Single(repository.Where(entity => entity.Id == id), id);
}
public static Order GetById(this IQueryable<Order> repository, int id)
{
return Single(repository.Where(entity => entity.Id == id), id);
}
// This method allows reporting more descriptive error messages.
[DebuggerStepThrough]
private static TEntity Single<TEntity, TKey>(IQueryable<TEntity> query,
TKey key) where TEntity : class
{
try
{
return query.Single();
}
catch (Exception ex)
{
throw new InvalidOperationException("There was an error " +
"getting a single element of type " + typeof(TEntity)
.FullName + " with key '" + key + "'. " + ex.Message, ex);
}
}
}
With these extension methods in place, it allows you to call those GetById and other methods from your code:
var employee = context.Employees.GetById(employeeId);
What the nicest thing is about this code (I use it in production) is that -once in place- it saves you from writing a lot of code for unit testing. You will find yourself adding methods to the AcmeRepositoryExtensions class and properties to the AcmeUnitOfWork class when new entities are added to the system, but you don't need to create new repository classes for production or testing.
This model has of course some shortcomes. The most important perhaps is that LINQ to SQL isn't abstract away completely, because you still use the LINQ to SQL generated entities. Those entity contain EntitySet<T> properties which are specific to LINQ to SQL. I haven't found them to be in the way of proper unit testing, so for me it's not a problem. If you want you can always use POCO objects with LINQ to SQL.
Another shortcome is that complicated LINQ queries can succeed in test but fail in production, because of limitations (or bugs) in the query provider (especially the EF 3.5 query provider sucks). When you do not use this model, you are probably writing custom repository classes that are completely replaced by unit test versions and you will still have the problem of not being able to test queries to your database in unit tests. For this you will need integration tests, wrapped by a transaction.
A last shortcome of this design is the use of Insert and Delete methods on the Unit of Work. While moving them to the repository would force you to have a design with an specific class IRepository<T> : IQueryable<T> interface, it prevents you from other errors. In the solution I use myself I also have InsertAll(IEnumerable) and DeleteAll(IEnumerable) methods. It is however easy to mistype this and write something like context.Delete(context.Messages) (note the use of Delete instead of DeleteAll). This would compile fine, because Delete accepts an object. A design with delete operations on the repository would prevent such statement from compiling, because the repositories are typed.
UPDATE: I wrote a blog post on this subject that describes this solution in even more detail: Faking your LINQ provider.
I hope this helps.
If combining unit of work and repository patterns, some people advocate that UoW should be managed outside of repository so that you could create two repositories (say, CustomerRepository and OrderRepository) and pass them the same UoW instance ensuring that all the changes to the DB will be done atomically when you finally call UoW.Complete().
In a mature DDD solution however, there should not be need for both UoW and a repository. This is because is such a solution aggregate boundaries are defined is such a way, that there is no need of atomic changes involving more than one repository.
Does this answer your question?

Resources