C# Repository with multiple constraints and inheritance - c#

i wasn't able to find a similar issue but feel free to redirect me if i just missed it.
I am trying to get familiar with the Repository pattern.
I'll give you an example of the code i'm trying to get to work unsuccessfully.
These are the classes and interfaces that represent the entity i'm using.
public class AbsObj
{
public string Code { get; set; }
}
public interface IAbsObj
{
bool Save();
}
public class User : AbsObj
{
public string Language{get; set;}
}
public class DbUser : User, IAbsObj
{
public bool Save()
{
return true;
}
}
Then to the repository Interface
public interface IRepository<T>
{
void Add(T value);
void Update(T value);
void Delete(T value);
}
The generic Repository
public class Repository<T> : IRepository<T> where T : AbsObj, IAbsObj
{
protected List<T> _lst;
public Repository()
{
_lst = new List<T>();
}
public void Add(T value)
{
}
public void Update(T value)
{
}
public void Delete(T value)
{
}
public bool Save()
{
for (int i = 0; i < _lst.Count; i++)
{
_lst[i].Save();
}
return true;
}
}
Then a more specific repository, which should handle the loading of the users from the db:
public class UserRepository<T> : Repository<T> where T : AbsObj, IAbsObj
{
public void Load()
{
DbUser us = new DbUser();
us.Code = "Cod";
us.Language = "IT";
_lst.Add(us);
}
}
I created the DBUser class just to have the freedom to create an XMLUser in the future which would handle a different type of saving.
It inherits from User which in turn inherits from AbsObj.
It implements IAbsObj.
Nonetheless i got a compile time error when i try to add to the list the DbUser object created, stating that it's impossible to convert from DBUser to T.
Given the constraints i tought it was possible: what am i missing here?
Thanks in advance for any help!

Your UserRepository definition could be:
public class UserRepository : Repository<DbUser>
{
....
}
But since you want to make it generic for XMLUser as well:
public class UserRepository<T> : Repository<T> where T: User, new()
{
public void Load()
{
User us = new T() as User;
us.Code = "Cod";
us.Language = "IT";
_lst.Add(us);
}
}
To use:
new UserRepostitory<DbUser>();
new UserRepostitory<XmlUser>();

Related

EntityFramework.sqlServerCompact and Repository pattern MVVM

I have a WPF application, I have used MVVM architecture, database sql server compact 4.
Entityframework.sqlserverCompact database first, and I used a generic repository pattern as follows:
public interface IRepository: IDisposable
{
IQueryable<T> All<T>() where T : class;
void InsertAsync<T>(T entity) where T: class ;
Task<T> GetByIdAsync<T>(int id) where T: class ;
Task EditAsync<T>(T entity) where T : class;
Task DeleteAsync<T>(T entity) where T : class;
}
The class that implement the Repository
public class TryitRepository : IRepository
{
private readonly MyEntityContext context;
public TryitRepository()
{
this.context = new MyEntityContext();
}
public IQueryable<T> All<T>() where T : class
{
return this.context.Set<T>();
}
public void Dispose()
{
if (this.context != null) this.context.Dispose();
}
public void InsertAsync<T>(T entity) where T : class
{
this.context.Set<T>().Add(entity);
this.context.SaveChanges();
}
}
// ViewModel
public class ArticleViewModel : ObjectBase
{
public readonly IRepository article;
public ArticleViewModel()
{
article = new TryitRepository();
this.LoadData();
}
private void LoadCommand()
{
this.EditCommand = new CustomCommand(this.EditArticle, this.CanEditArticle);
this.SaveCommand= new CustomCommand(this.SaveArticle, this.CanSaveArticle);
this.DeleteCommand = new CustomCommand(this.DeleteArticle, this.CanDeleteArticle);
}
private bool CanSaveArticle(object obj)
{
return true;
}
private void SaveArticle(object obj)
{
Article artikel = new Article() { Name = "newarticle", Color = "Pink", Price = 125.95, Articlenr = 15547878, Items_In_Package= 12 };
article.InsertAsync<Article>(artikel);
this.LoadData();
}
When the SaveArticle is fired, everything runs well, I see the new article on the list (ListView) but not in the database.
what am I doing wrong?
Thanks in advance.
Solved!
see answer of ErikEJ in the link below:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/e7f7a713-b0fd-4716-a19d-4421e8be4c88/forcing-db-changes-to-commit-in-sql-ce-?forum=sqlce

An abstract class which can be derived by database classes

This is my abstract class:
namespace MusicStoreApp.BLL.Master
{
public abstract class Master<T>
{
MusicStoreEntities db = new MusicStoreEntities();
public void Add(T item)
{
db.T.Add(item);
db.SaveChanges();
}
}
}
This is my target output in the other classes:
public class AlbumRepository : Master<Album>
{
public void Add(Album item)
{
db.Albums.Add(item);
db.SaveChanges();
}
}
public class ArtistRepository : Master<Artist>
{
public void Add(Artist item)
{
db.Artists.Add(item);
db.SaveChanges();
}
}
What i am tring to do here, that i should create a reusable interface-like class. So, i can just type the name of the T reference and it will create the rest of the codes for me.
The way your sample is setup can't work because T needs to point to two different classes (the specific instance and the DbSet that contains that class). Instead, try this:
namespace MusicStoreApp.BLL.Master
{
public abstract class Master<T>
{
MusicStoreEntities db = new MusicStoreEntities();
public void Add(T item)
{
db.Entry(item).State = System.Data.Entity.EntityState.Added;
db.SaveChanges();
}
}
}
You don't need this T anonymous type. Just do something like this:
public abstract class Master
{
public abstract void Add(Master item);
}
Then you can just inherit the Master like this:
public class Album : Master
public override void Add(Album item)
{
db.Albums.Add(item);
db.SaveChanges();
}
}
If you want to use a repository for the add just remove the add function from master and make interface and inherit from it:
public interface IMasterRepository
{
public void Add(Master item);
}
public class AlbumRepository : IMasterRepository
public override void Add(Album item)
{
db.Albums.Add(item);
db.SaveChanges();
}
}
But don't mix the entity classes with the repositories.
You are mixing abstract with generic class. The former contains something that requires to be implemented by the inheritors while the later provides common implementation that differs by some type(s) of the objects involved. From your explanation (and since your "abstract" class does not contain any abstract method), looks like you need a generic class. Something like this
public class Master<T>
{
MusicStoreEntities db = new MusicStoreEntities();
public void Add(T item)
{
db.Set<T>().Add(item);
db.SaveChanges();
}
}
public class AlbumRepository : Master<Album> { }
public class ArtistRepository : Master<Artist> { }
Note that you don't even need the concrete classes (if that's all they are supposed to do).
You can do so by using reflection.
get property name
string PropertyName = T.GetType().Name + "s";
retrive the entity property
var property = db.GetType().Properties.Where(x => x.Name.CompareTo(PropertyName) == 0).FirstOrDefault();
then work with it directly
Thank you for all of your effort to answer :).
I found my answer, I hope it will help you too:
public abstract class RepositoryBase<T>:IRepository<T> where T:class
{
public void Add(T item)
{
db.Set<T>().Add(item);
db.SaveChanges();
}
public void Update(int id,T item)
{
db.Entry(db.Set<T>().Find(id)).CurrentValues.SetValues(item);
db.SaveChanges();
}
public void Delete(T item)
{
db.Set<T>().Remove(item);
db.SaveChanges();
}
public List<T> SelectAll()
{
return db.Set<T>().ToList();
}
public T SelectByID(int id)
{
return db.Set<T>().Find(id);
}
}

Setting the connection string of a DBContext in my repository class using Ninject

I have an MVC 5 application that uses EF 6 and implements Repository pattern with dependency injection using the DI container Ninject. The connection string for the dbcontext is stored in the Web.config file which the EF Context properly finds. Everything works fine. Lately, I have a requirement that the connection to my DBContext need to be determined at runtime and connect to different databases (but with exactly the same structure). So, I need to change the sql connectionstring part from the entity connectionstring at run-time before the repository is instantiated. I would really appreciate some help in doing it. I am not a DI guru; know just enough Ninject to get my things going.
Here is my Repository Base Interface:
public interface IRepositoryBase<T> where T : class
{
void Add(T entity, string userGuid = "");
void Delete(T entity);
// ... removed other method signatures for brevity
}
My Repository base implementation:
public abstract class RepositoryBase<D, T> : IRepositoryBase<T>, IDisposable
where T : class
where D : DbContext, new()
{
private Guid? currUserGuid = null;
private D dataContext;
protected D DataContext
{
get
{
if (dataContext == null)
dataContext = new D();
return dataContext;
}
set { dataContext = value; }
}
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
{
return DataContext.Set<T>().Where(predicate);
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = DataContext.Set<T>();
return query;
}
public virtual void Delete(T entity)
{
OperationStatus stat = TryDelete(entity);
}
// .... removed rest for brevity
}
Interface and implementation for concrete class:
public interface ICustomerRepository : IRepositoryBase<Customer>
{
Customer GetCustomerAndStatus( Guid custGuid );
}
public class CustomerRepository : RepositoryBase<PCDataEFContext, Customer>, ICustomerRepository
{
public Customer GetCustomerAndStatus( Guid custGuid )
{
return DataContext.Customers.Include( x => x.CustStatusType )
.SingleOrDefault( x => x.PKGuid == custGuid );
}
}
My Ninject dependency resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
kernel = new StandardKernel();
AddBindings();
}
public IKernel Kernel { get { return kernel; } }
private void AddBindings()
{
kernel.Bind<ICustomerRepository>().To<CustomerRepository>();
// ... other bindings are omitted for brevity
}
}
and finally, here is my Entity Framework generated DBContext:
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base("name=PCDataEFContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
}
All the above code works great! But as I said in the beginning, I don't know how to inject the connection string into my Repositorybase class at runtime so that I don't have to modify any of my inherited repositories (I have plenty of them). Someone please help.
Babu.
Could you do it like this?
public partial class PCDataEFContext : DbContext
{
public PCDataEFContext()
: base(Util.GetTheConnectionString())
{ }
}
public class MyDerivedContext : PCDataEFContext
{
public MyDerivedContext()
: base()
{ }
}
class Util
{
public static string GetTheConnectionString()
{
// return the correct name based on some logic...
return "name=PCDataEFContext";
}
}
Another way of doing it, could be in the RepositorBase class you defined, by altering the connectionstring after the creation of the dbcontext:
protected D DataContext
{
get
{
if (dataContext == null)
{
dataContext = new D();
dataContext.Database.Connection.ConnectionString = "the new connectionstring";
}
return dataContext;
}
set { dataContext = value; }
}

Optimize the use of Generic Repository using linq to sql c#

I've Generic Repository Class like this:
public class Repository : IDisposable
{
public static DataContext context { get; set; }
public static void Insert<T>(T item) where T : class
{
try
{
var table = context.GetTable<T>();
table.InsertOnSubmit(item);
context.SubmitChanges();
}
catch (Exception)
{
throw;
}
}
public void Dispose()
{
context.Dispose();
}
}
Above one is my Generic Class for Inserting Entity using Linq to sql.
I've total 10 entities in my datacontext and i'm writing 10 Insert methods like this(Example i'm providing 3 methods).
public void AddStudent(Student st)
{
Repository.Insert<Student>(st);
}
public void AddEmployee(Employee emp)
{
Repository.Insert<Employee>(emp);
}
public void AddStudent(Product prod)
{
Repository.Insert<Product>(prod);
}
like this I've 10 methods. is there a way to optimize this code. like this
I want to create a class with Add method and i'll use this add method entire my app where ever it is required.
public class Class1
{
public void Add(Table table)
{
Repository.Insert<Table>(table);
}
}
I want to use like this Class1 cls1 = new Class1(); cls1.Add(StudentObject);
can please suggest the way to implement class.
You could define a generic class rather than just a method:
public class Repository<T> : IDisposable
{
public static DataContext context { get; set; }
public static void Insert(T item)
{
var table = context.GetTable<T>();
table.InsertOnSubmit(item);
context.SubmitChanges();
}
public void Dispose()
{
context.Dispose();
}
}
And you then get the following, rather than all the additional methods:
var repo = new Repository<Product>();
repo.Insert(aProduct);

How to create an abstract method with a parameter of type of implementing class

I have got a abstract class with an abstract method taking a parameter of the type of the implementing class. I can achieve this by generics like this:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
}
class MyClass : Clazz<MyClass>
{
public override void CopyFrom(Clazz<MyClass>)
{
// implementation
}
}
Unfortunately I need in one of the implementing classes a list of Clazz<T> elements.
So how can I achieve this?
Of cause List<Clazz<T>> does not work.
List<Clazz<MyClass>> is too restrictive.
Removing the generics and the abstract method does work (my current solution), but this way I could forget to implement the CopyFrom() method in one of the implementing classes.
Edit: Here comes a more detailed example:
I've got an abstract class:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
// ...
}
And a derived class:
class MyDerivedClass : Clazz<MyDerivedClass >
{
public string Text;
private readonly List<MySubClass> _list = new List<MySubClass>();
public override void CopyFrom(MyDerivedClass source)
{
Text = source.Text;
}
private List<Clazz> GetAllItems()
{
List<Clazz> list = new List<Clazz>();
list.Add(this);
list.AddRange(_list);
}
private class MySubClass : Clazz<MySubClass>
{
public int Number;
public override void CopyFrom(MySubClass source)
{
Number = source.Number;
}
}
}
There are several other deriving classes, the GetAllItems() Method is only needed in MyDerivedClass.
would this suffice? without more details it is hard to tell.
interface ICopyMaker
{
void CopyFrom(ICopyMaker source);
}
abstract class Clazz<T> : ICopyMaker
{
public abstract void CopyFrom(Clazz<T> source);
void ICopyMaker.CopyFrom(ICopyMaker source)
{
var src = source as Clazz<T>;
if (src == null) return; // know how to copy only from the instances of the same type
CopyFrom(src);
}
}
class MyClass : Clazz<MyClass>
{
private List<ICopyMaker> _list = new List<ICopyMaker>();
public override void CopyFrom(Clazz<MyClass> c)
{
//implementation
}
}
You can make the respective method generic, too, and introduce a constraint that takes T into account. If I understand well what you want to achieve, you can do this:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
public abstract void ProcessList<TDescendant>(List<TDescendant> list)
where TDescendant : Clazz<T>;
}
class MyClass : Clazz<MyClass>
{
public override void CopyFrom(Clazz<MyClass> source)
{
// implementation
}
public override void ProcessList<TDescendant>(List<TDescendant> list)
{
// implementation
}
}
You can also easily include list processing in a descendant, like this:
class MyOtherClass : Clazz<MyOtherClass>
{
public override void CopyFrom(Clazz<MyOtherClass> source)
{
// implementation
}
// this list processing is inherited
public override void ProcessList<TDescendant>(List<TDescendant> list)
{
// implementation
}
// this list processing is specific to this descendant only
public void ProcessMyClassList<TDescendant>(List<TDescendant> list)
where TDescendant : Clazz<TMyClass>
{
// implementation
}
}
Then use can declare a descendant of MyClass, which in turn is a Clazz<T>, T being MyClass:
class MyDescendant : MyClass
{
}
The following works:
List<MyDescendant> list = new List<MyDescendant>();
new MyClass().ProcessList(list);
In case of MyOtherClass, the situation is a little bit different. ProcessMyClassList accepts a list of Clazz<T> or its descendants; however, not those related to MyOtherClass but to the good-ol' MyClass. This code works:
List<MyDescendant> list = new List<MyDescendant>();
new MyOtherClass().ProcessMyClassList(list); // this works
But the following won't compile:
List<MyOtherClass> list = new List<MyOtherClass>();
new MyOtherClass().ProcessList(list); // this works
new MyOtherClass().ProcessMyClassList(list); // this doesn't
Thank's everyone for your answers, but I think I have figured out a solution I can live with:
I will remove the generics and add a typecheck, like in the solution from anikiforov:
Abstract class:
abstract class Clazz
{
public abstract void CopyFrom(Clazz source);
}
And the derived class:
class MyDerivedClass : Clazz
{
public string Text;
private List<MyNestedClass> _list;
public override void CopyFrom(Clazz source)
{
var src = source as MyDerivedClass;
if (src == null) return;
Text = src.Text;
}
public List<Clazz> GetAllItems()
{
var list = new List<Clazz>();
list.Add(this);
list.AddRange(_list);
return list;
}
class MyNestedClass : Clazz
{
public int Number;
public override void CopyFrom(Clazz source)
{
var src = source as MyNestedClass;
if (src == null) return;
Number = src.Number;
}
}
}

Categories

Resources