Optimize the use of Generic Repository using linq to sql c# - 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);

Related

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);
}
}

Optimize my Code logic without singletion

public interface IHandler
{
List<string> Run();
}
public class Base
{
void methodA();
}
public Class Der1 : Base , IHandler
{
List<string> Run()
{ //Generate huge records
}
}
public Class Der2 : Base , IHandler
{
List<string> Run()
{//Generate huge records
}
}
public Class Der3 : Base , IHandler
{
List<string> Run()
{//Generate huge records
}
}
Currently Run() is getting executed across all the derived class and generating same set of records. I want this to optimize.
Move the RecordGeneration process inside Run() to a common class/function and get executed once and prepare the necessary records. All the Derived class will use this "RecordGeneration" to get the already Generated Records.
Note: I cannot implement Singleton pattern.
You can use Lazy<T>:
private Lazy<List<string>> l;
public Der1
{
l = new Lazy<List<string>>(() => Run());
}
public List<string> ResultOfRun
{
get
{
return l.Value();
}
}
To extend on my initial answer, if the method has the same output across all methods, you can do this:
public class Base
{
private Lazy<List<string>> l = new Lazy<List<string>>(() => RunStatic());
private static List<string> RunStatic()
{
//
}
public List<string> ResultOfRun
{
get
{
return l.Value();
}
}
void methodA();
}
Then you only have to call it in Run, which could be in the base class to if it implements the interface:
public Class Der1 : Base , IHandler
{
List<string> Run()
{
return this.ResultOfRun;
}
}

C# Repository with multiple constraints and inheritance

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>();

C# cast generic T in abstract class<T> to dynamic

This is what I want to do in C# (within class Helper - without generic arguments),
List<AbstractClass<dynamic>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<dynamic>) thing);
}
This helper class would take and work with AbstractClass<> objects and give back AbstractClass<> of specific generic type. AbstractClass<T> contains many functions which return T / take in T like public T Invoke().
For Helper class T cannot be known beforehand. The Add<T>(.. thing) function is not in a class of type T.
To be used like this in Helper class's functions,
foreach(var c in data.Where(x => ...))
{
// public T Invoke() { ... } function within AbstractClass<T>
var b = c.Invoke();
// logic
}
This also fails,
List<AbstractClass<object>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<object>) thing);
}
Now I think I can have,
List<dynamic> data; // or List<object> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add(thing);
}
but I want the constraint that List named data has only elements of type like
ConcreteClass : AbstractClass<OtherClass>
So we would know that there is an public T Invoke() function but we do not know what it returns. This is helpful to avoid mistakes of say misspelling Invocke and only knowing at run-time.
I want to avoid casting to dynamic every time to invoke functions that give back generic type T
To do what you want to do you are going to need to use a Contravariant interface
public class Program
{
static void Main()
{
var m = new Helper();
m.Add(new ConcreteClass());
m.Process();
}
class Helper
{
List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();
public void Add(IAbstractClass<OtherClassBase> thing)
{
this.data.Add(thing);
}
public void Process()
{
foreach(var c in data.Where(x => x.ShouldBeProcessed()))
{
var b = c.Invoke();
Console.WriteLine(b.Question);
var castData = b as OtherClass;
if (castData != null)
Console.WriteLine(castData.Answer);
}
}
}
public interface IAbstractClass<out T>
{
bool ShouldBeProcessed();
T Invoke();
}
abstract class AbstractClass<T> : IAbstractClass<T>
{
public bool ShouldBeProcessed()
{
return true;
}
public abstract T Invoke();
}
class ConcreteClass : AbstractClass<OtherClass>
{
public override OtherClass Invoke()
{
return new OtherClass();
}
}
class OtherClassBase
{
public string Question { get { return "What is the answer to life, universe, and everything?"; } }
}
class OtherClass : OtherClassBase
{
public int Answer { get { return 42; } }
}
}
You do not need to tell Add what kind of class you are passing it, all that matters is it derives from the type specified. You could do public void Add(IAbstractClass<object> thing) and every class would work, but Invoke() would only return objects inside the foreach loop.
You need to figure out what is the most derived class you want Invoke() to return and that is what you set as the type in the list.
Maybe this will work for you:
public class Program
{
static void Main()
{
var m1 = new Helper<OtherClass>();
m1.Add(new ConcreteClass());
var m2 = new Helper<int>();
m2.Add(new ConcreteClass2());
}
class Helper<T>
{
List<AbstractClass<T>> data = new List<AbstractClass<T>>();
public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
{
this.data.Add(thing);
}
}
class AbstractClass<T> { }
class OtherClass { }
class ConcreteClass : AbstractClass<OtherClass> { }
class ConcreteClass2 : AbstractClass<int> { }
}

Is It possible to use the second part of this code for repository patterns and generics

Is there any issues in using version 2,to get the same results as version 1.
Or is this just bad coding.
Any Ideas
public class Customer
{
public int CustomerID { get; set; }
public string EmailAddress { get; set; }
int Age { get; set; }
}
public interface ICustomer
{
void AddNewCustomer(Customer Customer);
void AddNewCustomer(string EmailAddress, int Age);
void RemoveCustomer(Customer Customer);
}
public class BALCustomer
{
private readonly ICustomer dalCustomer;
public BALCustomer(ICustomer dalCustomer)
{
this.dalCustomer = dalCustomer;
}
public void Add_A_New_Customer(Customer Customer)
{
dalCustomer.AddNewCustomer(Customer);
}
public void Remove_A_Existing_Customer(Customer Customer)
{
dalCustomer.RemoveCustomer(Customer);
}
}
public class CustomerDataAccess : ICustomer
{
public void AddNewCustomer(Customer Customer)
{
// MAKE DB CONNECTION AND EXECUTE
throw new NotImplementedException();
}
public void AddNewCustomer(string EmailAddress, int Age)
{
// MAKE DB CONNECTION AND EXECUTE
throw new NotImplementedException();
}
public void RemoveCustomer(Customer Customer)
{
// MAKE DB CONNECTION AND EXECUTE
throw new NotImplementedException();
}
}
// VERSION 2
public class Customer_New : DataRespository<CustomerDataAccess>
{
public int CustomerID { get; set; }
public string EmailAddress { get; set; }
public int Age { get; set; }
}
public class DataRespository<T>
where T:class,new()
{
private T item = new T();
public T Execute { get { return item; } set { item = value; } }
public void Update()
{
//TO BE CODED
}
public void Save()
{
//TO BE CODED
}
public void Remove()
{
//TO BE CODED
}
}
class Program
{
static void Main(string[] args)
{
Customer_New cus = new Customer_New()
{
Age = 10,
EmailAddress = "this#demo.com"
};
cus.Save();
cus.Execute.RemoveCustomer(new Customer());
// Repository Version
Customer customer = new Customer()
{
EmailAddress = "new#demo.com",
CustomerID = 10
};
BALCustomer bal = new BALCustomer(new CustomerDataAccess());
bal.Add_A_New_Customer(customer);
}
}
You have a lot of things going on that aren't making a lot of sense.
First of all, the names of properties should always be a noun (singular or plural) or a "being" verb like Is* or Has*. These are properties of an object, and should be similar to what you would say in response to a question like "Would you please describe your desk?" Execute is an operation, and should therefore be a method. Likewise, your naming conventions in Version 1 should be PascalCased which means no underscores and the first letter of all words should be capitalized. These aren't die-hard truths, but they are considered OOP common C# coding standards.
Secondly, the code in your main method isn't actually implementing anything in your generic class. The only thing your class is actually doing is creating an instance of CustomerDataAccess. The Save() method won't do anything, unless you specifically are able to call item.Save() In order to use your Save, Update, Delete functionality on your generic class, your CustomerDataAccess class will have to implement an interface expected by your generic class. For instance:
public interface IDataAccess<T> : where T : YourBaseObject {
public void Update(T item);
public void Save(T item);
public void Remove(T item);
}
public class Customer : YourBaseObject {
public int CustomerID { get; set; }
public string EmailAddress { get; set; }
public int Age { get; set; }
}
public class CustomerDataAccess :
DataRespository<IDataAccess<Customer>> {
public void PerformCustomerOnlyAction(Customer customer) {
/* do stuff */
}
}
Now, you can create a generic class that handles basic CRUD functionality, and all other functionality is accessible through the BaseRepository property.
/* e.g. T = IDataAccess<Customer>, K = Customer */
public class DataRespository<T>
where T : IDataAccess<K>, new()
where K : YourBaseObject, new()
{
private T _base;
public T BaseRepository {
get {
if(_base == null)
_base = Activator.CreateInstance<T>();
return _base;
}
}
public void Update(K item) { /* functionality for YourBaseObject */ }
public void Save(K item) { /* functionality for YourBaseObject */ }
public void Remove(K item) { /* functionality for YourBaseObject */ }
}
class Program
{
static void Main(string[] args)
{
var repository = new CustomerDataAccess();
Customer c = new Customer {
Age = 10,
EmailAddress = "this#demo.com"
};
repository.Save(c);
// This pass-through is no longer needed, but shown as example
// repository.BaseRepository.PerformCustomerOnlyAction(c);
repository.PerformCustomerOnlyAction(c);
}
}
NOTE I did the above code from scratch/memory. The generic type constraints may not work exactly as I have them.
ASP.NET 3.5 Unleashed by Stephen Walther has a couple of chapters on creating a repository pattern which is setup similarly to what you're trying to accomplish in Version 2. He also splits processing up between a business logic layer and a data access layer. Although the book is huge (nearly 2000 pages) and many of the code examples are redundant or better left as part of the CD, he goes pretty in-depth for beginner-to-intermediate range. It's available used on Amazon for around $25.
I think while implementing object model of your application you just have to ask yourself a number of questions as though you are make object design review of your collegue code.
Why CustomerAccessLayer implements interface? Is there will be a number of layers implementing this Interface. Or maybe you are expecting any polymorph behaviour from classes implements this interface? Or maybe you will separate interface to standalone module and will provide its functionality though any kind of service?
Why do you need BALCustomer class? Why you could not make calls directly to CustomerAccesLayer? And, have i already spoke about codesyle? :)
If DataRepository have a generic behaviour and will provide a number of AccessLayers throw Execute property why it is have its own methods?
I think could be continued... I hope you've catch my point?

Categories

Resources