Entity Framework and Repository Pattern conceptual difficulties - c#

I am making an intranet website using ASP.NET MVC and SQL Server 2012. I am making a repository and architecturing with Onion Architecture. My problem is that the company in which I am working, already has several Server DBs in which the tables have no relations between each other. Instead, there are tables to map these relations. For example a table User, and a table Document have a table User_joint_Document to make a relation, containing both IDs (IDDocument and IDUser). Now when I write my generic repository:
class Repository<T> : IRepository<T> where T : class
the problem is the Generic type T makes no sense and I can't affect values in my model using EF queries which is normal, and what would be great would be to have a parent class BaseEntity to have IDs defined for each tables, then I can write:
class Repository<T> : IRepository<T> where T : BaseEntity
And all my table models would inherit from BaseEntity. But that would also mean rewriting the whole DB in a relational manner and mapping every DB POCO manually(correct me if I'm wrong), and I do not have the skillset to do this(there are over 300 tables in the different server DBs and I lack proper knowledge and experience to do this kind of operation).
Is there a way to keep my original DB structure, and still write a Generic Repository? How would one go about doing this?
EDIT To clarify my question because #saeb answered partially to my question. Can I have a generic repo without having a parent class for my DB POCOs? Or do I need it in order to then have only ONE repository to rule them all? For example:
class Repository<T>:IRepository<T> where T : class
{
private readonly ApplicationContext context;
private DbSet<T> entities;
public Repository(PrincipalServerContext context)
{
this.context = context;
entities = context.Set<T>();
}
public T Get(long id)
{
return entities.SingleOrDefault(s => s.IDUser == id);
//This does not work, IDUser isn't recognized
}
Thanks for your help!

... has several Server DBs in which the tables have no relations between each other ...
But they do have a relationship, a Many-to-Many relationship, which is defined via that third mapping table (whether that's a correctly defined relationship is another topic)
... the problem is the Generic type T makes no sense and I can't affect values in my model using EF queries ...
Why doesn't it and why can't you? considering your table examples, you'd have two entities, User and Document and they'd look like this:
public class User
{
public int IDUser { get; set; }
public virtual ICollection<Document> Documents { get; set; }
...
}
public class Document
{
public int IDDocument { get; set; }
public virtual ICollection<User> Users { get; set; }
...
}
And you can use the fluent API in your context's OnModelCreating to set up the relationship via the third table:
public class YourContext: DbContext
{
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasMany<Document>(u => u.Documents)
.WithMany(d => d.Users)
.Map(userJointDocument =>
{
userJointDocument.MapLeftKey("IDUser");
userJointDocument.MapRightKey("IDDocument");
userJointDocument.ToTable("User_joint_Document");
});
}
...
}
And then you can query Users and Documents in your repository as you would if there was a direct relationship between them. Here are more good sources to learn more about this if you like.

As far as I can see your problem, there is now way of achieving this without putting at least a base class or an interface to your entities/POCOs
You can play around with expressions for achieving a generic Repository
public interface IEntity<T> where T : class
{
Expression<Func<T, bool>> GetByIdPredicate(long id);
}
public partial class User : IEntity<User>
{
public int UserID { get; set; }
public Expression<Func<User, bool>> GetByIdPredicate(long id)
{
return (User entity) => entity.UserID == id;
}
}
class Repository<T>:IRepository<T> where T : class, IEntity, new()
{
private readonly ApplicationContext context;
private DbSet<T> entities;
T dummyEntity;
public Repository(PrincipalServerContext context)
{
this.context = context;
entities = context.Set<T>();
dummyEntity = new T();
}
public T Get(long id)
{
return entities.SingleOrDefault(dummyEntity.GetByIdPredicate(id));
}
There's probably a cleaner way that also gets rid of the dummyEntity field

Related

Return a list from Entity Framework, based on string parameter

I have a database first Entity Framework setup. Usually, I create procedures like this, to return a list of a defined object in my model.
public List<Employees> GetEmployees()
{
var tables = _crmContext.Employees.ToList();
return tables;
}
That works fine but the case I can't figure out, it different. I want to return a list of an object in the entity framework model, based on a parameter passed to the procedure.
I was trying something like this, but it's not working and I also don't know if is the right approach.
public List<T> GetValuesFromTable(string table)
{
var results = _crmContext."table".ToList();
return results;
}
Thanks for the help.
I think the Generic Repository Pattern is what you're looking for. In this way, you can call all the tables you have given type with a single method. Example
Repository.cs
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected readonly DbContext Context;
public Repository(DbContext context)
{
this.Context = context;
}
public IEnumerable<TEntity> GetAll()
{
return Context.Set<TEntity>().ToList();
}
}
IRepository.cs
public interface IRepository<TEntity> where TEntity : class
{
IEnumerable<TEntity>GetAll();
}

Remove an entity without fetching it in the generic repository pattern entity framework

I am trying to delete an entity of Employee from the database which contains different tables like Employee, Project, Skills using a generic repository pattern.
namespace Information.Repository
{
public class IRepositoy<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly ApplicationDbContext _dbContext;
public IRepositoy(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public void Remove(int id)
{
TEntity element = _dbContext.Set<TEntity>().Find(id);
_dbContext.Set<TEntity>().Remove(element);
}
}
}
When the above Remove method is called it makes two database call
One for getting the entity.
Second for deleting it.
I have found the query like the below one which executes with single SQL query
when the entity type(Employee or Project or Skill) is known
public void Remove(int id)
{
Employee employee = new Employee { EmployeeId = id };
_dbContext.Entry(employee).State = EntityState.Deleted;
}
can anyone please suggest me how to delete an entity without fetching it using a generic repository pattern similar to the above example.
Using raw SQL
Entity Framework doesn't allow you to delete an object that you haven't loaded (or attached). This also extends to conditional deletes (e.g. deleting all users named John) as it requires you to load the users before deleting them.
You can get around this by executing raw SQL. It's not ideal as you tend to use EF so you don't have to write SQL, but the lack of a decent delete behavior (without loading) makes this an acceptable solution.
Something along the lines of:
using (var context = new FooContext())
{
var command = "DELETE * FROM dbo.Foos WHERE Id = 1";
context
.Database
.ExecuteSqlCommand(command);
}
Where relevant, don't forget about SQL injection protection. However, it's usually a non-issue for simple deletes as the FK is usually a GUID or int, which doesn't expose you to injection attacks.
Making it generic
The example you posted works as well, but you're probably not using it because it can't easily be made generic-friendly.
What I tend to do in all my EF projects is to have an (abstract) base class for all my entities, something along the lines of:
public class BaseEntity
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime? UpdatedOn { get; set; }
public string UpdatedBy { get; set; }
}
An interface would also work, I just prefer a base class here.
The audit fields are not part of this answer but they do showcase the benefits of having a base class.
When all your entities inherit from the same base class, you can put a generic type constraint on your repositories which ensures that the generic type has an Id property:
public class IRepositoy<TEntity> : IRepository<TEntity> where TEntity : BaseEntity
At which point you can generically implement your proposed solution:
public void Remove(TEntity obj)
{
dbContext.Entry(obj).State = EntityState.Deleted;
}
You can also specify a parameterless constructor type constraint:
where TEntity : BaseEntity, new()
which enables you to instantiate your generic type as well:
public void Remove(int id)
{
TEntity obj = new TEntity() { Id = id };
dbContext.Entry(obj).State = EntityState.Deleted;
}
Note
There is a generic raw SQL solution as well, but I've omitted it as it is more complex because it requires you to retrieve the table name based on the entity type.
The raw SQL variant is only valuable in cases where you want to execute conditional deletes (e.g. removing all entities whose id is an even number).
However, since most conditional deletes are entity-specific, this means that you generally don't need to make them generic, which makes the raw SQL approach more viable as you only have to implement it in a specific repository and not the generic one.
You still have to fetch it. Entity Framework caches your dbSets so it's usually pretty quick. Use the same context like so:
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
Where dbSet =
context.Set<TEntity>();
The current limitation of Entity Framework is, in order to update or delete an entity you have to first retrieve it into memory. However there are few alternatives to delete a specific record.
You can try ExecuteSqlCommandto delete a specific record
_dbContext.Database.ExecuteSqlCommand("Delete Employee where EmployeeId = {0}", id );
or try using EntityFramework.Extended Library to delete a specific record
_dbContext.Settings.Where(s=> s.EmployeeId == id).Delete();

C# Entity Framework DBContext

I am trying to learn Code First EF6 and I am confused regarding DBContext.
The database I will be working on contains 800+ tables, while when working of specific parts of the application I am only dealing with 1-10 tables.
So my question is; would not having a DBContext involving 800+ Classes have a big negative impact on system resources?
I guess I am new to this technology and confused regarding the actual meaning of the information that I am taking in during my research.
Thank you.
NOTE: Thank you for your inputs. Please take a look at this post: Using multiple DbContexts with a generic repository and unit of work. There it states I cannot have tables in separate contexts that relate to each other?!
But in a real world scenerio my understanding is that it is common to break up the table relationships in focused areas, how is this done in Code First EF? Thanks again.
Updated
If you are using Repository Pattern, you cannot go make multiple DbContext, You Create One Generic, And pass it to your Generic Repository like below :
public class Repository<T> : IRepository<T>
where T : EntityBase
{
internal MyDbContext context;
internal DbSet<T> dbSet;
public Repository()
{
context = new MyDbContext();
this.dbSet = context.Set<T>();
}
public void Add(T entity)
{
dbSet.Add(entity);
}
public void Delete(T entity)
{
dbSet.Remove(entity);
}
public void Delete(int id)
{
dbSet.Remove(dbSet.Find(id));
}
public T GetById(int id)
{
return dbSet.Find(id);
}
public IEnumerable<T> GetAll()
{
return dbSet.AsEnumerable();
}
public void Update(T entity)
{
dbSet.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
}
And you should include your DbSets there as well.
If you are doing EF Code-First then its yours to design your POCO class based on how many are needed but no more. But based on what you said about 800 tables i think you may want to try Database-First Approach rather. i suggest you this article very carefully as it explain everything you need.
Update:
If you Approach this from DataBase-First: Ado.NET Entity Model Creates your DbContext for you! If you take a closer look at the .Edmx file it is basically your POCO Classes within.
Now if you try Code-First Approach, lets say you have this DbContext Class:
public class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyConnection")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, YourApplication.Migrations.Configuration>("MyConnection"));
}
//Every time you need to add new Table you add them here.
public DbSet<Users> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//And Map them here
modelBuilder.Configurations.Add(new UsersMap());
}
}
You just add a new DbSet<Class> to your DbContext like below:
public DbSet<POCO CLASS> CLASS { get; set; }
And so on, i normally create a DbContext for Every Area i have in my MVC Application. So you can go like Admin Area -> AdminDbContext And so on.
You only need the tables you are working with in your db context (if the db already exists). The only reason you'd need a db context with all the tables would be if you want to recreate the whole db from scratch.
Take a look at the bounded context pattern from DDD: http://martinfowler.com/bliki/BoundedContext.html

Can we use Generic Repository without using EF? Is it a good practise?

I have an application in which the person who designed the application had used a dbml to manage db classes. But we have another database that we often need to connect to and we've been using ado.net normally to connect to it as we cannot use same dbml for it. However, I do not personally like using a LINQ database as the generated auto-code causes errors whenever we add a new table or property.
I've been trying to implement a repository pattern with self-declared classes to map to each table but to manage operations on each table, we need a separate repository for each entity. I'm not sure if I'm on the right path using this pattern but if I'm not using EF in this case, can we have a generic repository to represent the general operations or just create separate repository for each entity that we create?
Also, for generic repository, I would appreciate if I can get some example or pointers to it.
Sorry if I sound redundant.
Thanks in advance!
Generic repository is a good idea if you will just use CRUD operations, (Create, Read, Update and Delete)
for me, i don't like much the to generate the database entities through DBML, i usually write entities and their mappings manually , here under some example of a project i am working on
first the model
public class Operator
{
public virtual string OperatorName { get; set; }
public virtual string LoginName { get; set; }
public virtual string Email { get; set; }
public virtual string PhoneNo { get; set; }
public virtual short Status { get; set; }
public virtual byte[] Password { get; set; }
}
UPDATE :
to make the repository independent of the provider you should define custom context which the repository will use
first define the interface
public interface IGenericContext
{
void Add<T>(T entity)
where T : class;
void Update<T>(T entity)
where T : class;
void Delete<T>(T entity)
where T : class;
IQueryable<T> GetIQueryable<T>()
where T : class;
}
here a sample of EF context that implements the IGenericContext interface
public class EFContext : DbContext, IGenericContext
{
public EFContext(string connectionName)
: base(connectionName)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.AddFromAssembly(this.GetType().Assembly);
base.OnModelCreating(modelBuilder);
}
public void Add<T>(T entity) where T : class
{
this.Set<T>().Add(entity);
this.SaveChanges();
}
public void Update<T>(T entity) where T : class
{
this.Set<T>().Attach(entity);
this.Entry(entity).State = EntityState.Modified;
this.SaveChanges();
}
public void Delete<T>(T entity) where T : class
{
this.Set<T>().Attach(entity);
this.Set<T>().Remove(entity);
this.SaveChanges();
}
public IQueryable<T> GetIQueryable<T>() where T : class
{
return this.Set<T>();
}
}
for EF, you will need to do the mappings yourself like below
public class OperatorMapping : EntityTypeConfiguration<Operator>
{
public OperatorMapping()
{
this.ToTable("Operators");
this.Property(t => t.OperatorName).IsRequired().HasColumnName("OperatorName");
this.HasKey(t => t.LoginName).Property(t => t.LoginName).HasColumnName("LoginName");
this.Property(t => t.Email).IsRequired().HasColumnName("Email");
this.Property(t => t.PhoneNo).HasColumnName("PhoneNo");
this.Property(t => t.Status).IsRequired().HasColumnName("Status");
this.Property(t => t.Password).IsRequired().HasColumnName("Password");
}
}
then a generic repository, this repository will use the IGenericContext instead of working on EF DBContext
public class Repository<TEntity>
where TEntity : class, new()
{
protected IGenericContext Context { get; set; }
public Repository(IGenericContext context)
{
Context = context;
}
public void Add(TEntity entity)
{
Context.Add(entity);
}
public void Update(TEntity entity)
{
Context.Update(entity);
}
public void Delete(TEntity entity)
{
Context.Delete(entity);
}
public List<TEntity> ToList()
{
return Context.GetIQueryable<TEntity>().ToList();
}
}
all you need to do is create the DBContext, pass it to the generic repository and do your operations
IGenericContext context = new EFContext("Infrastructure");
Repository<Operator> repository = new Repository<Operator>(context);
var operators = repository.ToList();
you can then implement another context that do the basic CRUD operations and still can use the same repository

I need to bind with Ninject to database and inject them to same repository in same time

Here some parts of my code
class NinjectWebCommon place where I need bind dada contexts.
It is just piece of the code, not complete classes.
private static void RegisterServices(IKernel kernel)
{
kernel.BindSharpRepository();
RepositoryDependencyResolver.SetDependencyResolver(new NinjectDependencyResolver(kernel));
kernel.Bind<DbContext>().To<EntitiesDbOne>().InRequestScope();
//kernel.Bind<DbContext>().To<EntitiesDbTwo>().InRequestScope();
}
Category Repository class where i need to have two databases in same time
public class CategoryRepository : ConfigurationBasedRepository<CategoryData, int>, ICategoryRepository
{
private readonly EntitiesDbOne _ctxOne;
private readonly EntitiesDbTwo _ctxTwo;
public CategoryRepository(EntitiesDbOne ctxOne, EntitiesDbTwo ctxTwo)
{
_ctxOne= ctxOne;
_ctxTwo= ctxTwo;
}
public CategoryData GetById(int Id)
{
//dummy data, just for usage two different dcContexts
var category = _ctxOne.Categories.Include((string) (x => x.MetaTags)).FirstOrDefault(x => x.Id == Id);
var categoryName = _ctxTwo.category.FirstOrDefault(x => x.Id == category.Id);
return category;
}
In my project I use SharpRepository(ConfigurationBasedRepository) and I use UnitOfWork. I think I can skip UnitOfWork because EntityFramework is doing all this (UnitOfWork patterns) job.
Booth of databases is EntityFramework one is CodeFirst approach other (DbTwo) modelFirst
public class EntitiesDbOne : DbContext
{
public DbSet<CategoryData> Categories { get; set; }
}
public partial class EntitiesDbTwo: DbContext
{
public EntitiesDbTwo()
: base("name=EntitiesDbTwo")
{
}
public DbSet<attributenames> attributenames { get; set; }
public DbSet<category> category { get; set; }
}
Please give me some links to examples I can use, I do not think I can manage this with simple explanation. Before I wrote this question, I had search for the answer here on the
Multiple DbContexts in N-Tier Application
EF and repository pattern - ending up with multiple DbContexts in one controller - any issues (performance, data integrity)?
This question by the name is complete in my situation but the code for me, is far different.
Multiple dbcontexts with Repository, UnitOfWork and Ninject
This one is multiple databases but use one per request, and I need two databases in the same request.
http://blog.staticvoid.co.nz/2012/1/9/multiple_repository_data_contexts_with_my_repository_pattern
site and other place.
I read about 20 suggestions, there are two close to my situation but probably not enough.
just as a basis for discussion:
What if you use:
kernel.Bind<EntitiesDbOne>().ToSelf().InRequestScope();
kernel.Bind<EntitiesDbTwo>().ToSelf().InRequestScope();
and use it like
public class CategoryRepository : ConfigurationBasedRepository<CategoryData, int>, ICategoryRepository
{
public CategoryRepository(EntitiesDbOne ctxOne, EntitiesDbTwo ctxTwo)
{
}
}
what's the issue then?

Categories