This is my first question here and i'm not very familliar with the C# terminology, so if i get some terms or definitions mixed up i appologize in advance.
I have set up a generic EF data access layer;
public class BaseService<TObject> where TObject : class
{
private DbContext Context;
private static readonly Lazy<BaseService<TObject>> lazy = new Lazy<BaseService<TObject>>(() => new BaseService<TObject>());
public static BaseService<TObject> Instance => lazy.Value;
public BaseService()
{
Context = new evEntities();
}
public BaseService(DbContext context)
{
Context = context;
}
public ICollection<TObject> GetAll()
{
return Context.Set<TObject>().ToList();
}
public async Task<ICollection<TObject>> GetAllAsync()
{
return await Context.Set<TObject>().ToListAsync();
}
public TObject Get(int id)
{
return Context.Set<TObject>().Find(id);
}
}
Together with this;
public static class DA
{
public static DataAccess.Categories Categories => new DataAccess.Categories();
public static DataAccess.Tags Tags => new DataAccess.Tags();
public static DataAccess.Users Users => new DataAccess.Users();
}
public static class DA<T> where T : class
{
public static BaseService<T> Base => new BaseService<T>();
}
So in my Business Layer i can do this;
public class Categories
{
public Categories() { }
public ICollection<Database.Categories> GetAll()
{
return DA.Categories.GetAll().ToList();
}
public async Task<ICollection<Database.Categories>> GetAllAsync()
{
return await DA.Categories.GetAllAsync();
}
public Database.Categories Get(int id)
{
return DA.Categories.Get(id);
}
}
For clarity. My EF creates classes/entities like 'Database.Categories' and 'Database.Users' which i pass as 'TObject' to my BaseService to get a standard way of pulling data from my database for all my entities.
Now my question. In a similar way i want to create a generic Business Layer. Like;
public class BusinessLogicBase<TModel>
{
public ICollection<TDBModel> GetAll()
{
return null;
}
public async Task<ICollection<TDBModel>> GetAllAsync()
{
return await DA.Categories.GetAllAsync();
}
public TDBModel Get(int id)
{
return DA.Categories.Get(id);
}
}
I want to be able to call the DA with a TObject like Database.Categories but this has to be dynamic, based on the type passed to the BusinessLogicBase. So i want to do something like this (which doesn't work);
private ???? DetermineDatabaseModel()
{
switch(typeof(TModell))
{
case Models.Categories:
return Database.Categories;
case Models.Users:
return Database.Users;
}
}
So i can do this;
public ICollection<TDBModel> GetAll()
{
var databaseModel = DetermineDatabaseModel()
return DA<databaseModel>().GetAll();
}
I hope you understand my question and can help me.
Thnx!
Sorry for the long post, and for all you 9gaggers, here's a potato... No just kidding, this is serious.
Have you tried something like:
public class BusinessLogicBase<TDBModel> where TDBModel : class {
public ICollection<TDBModel> GetAll() {
return DA<TDBModel>.Base.GetAll();
}
}
UPDATE 1:
Maybe it would help You if you try to write it without generics first and then convert it into more general pattern using generics. There are some missteps that are easier to solve without generics.
Method public ICollection<TDBModel> GetAll() can't return ICollection<TDBModel> because type parameter TDBModel is not defined either in class signature or method signature. I makes more sense if you define it like this:
public class BusinessLogicBase<TModel>
{
public ICollection<TModel> GetAll()
{
return null;
}
}
UPDATE 2:
try this simple console app to demonstrate dynamic keyword and watch what is stored in variables categories and users.
UPDATE 3:
Based on fiddle - I've changed IBaseService<dynamic> to dynamic:
public class BL<TModel>
{
// This is what i want to make dynamic.
// how do i create a return type that i can use in DA<>..
private Type testDetermineDatabaseModel()
{
switch(typeof(TModel).Name){
case "Categories":
return typeof(Database.Categories);
case "Users":
return typeof(Database.Users);
}
return null;
}
public ICollection<TModel> testGetAll()
{
var databaseModel = testDetermineDatabaseModel();
// return DA<databaseModel>().Base.GetAll();
return new List<TModel>();
}
// NEW
// I have constructed the following.
private dynamic baseService;
public dynamic DetermineDatabaseModel()
{
switch (typeof(TModel).Name)
{
case "Categories":
return new BaseService<Database.Categories>();
case "Users":
return new BaseService<Database.Users>();
default:
return null;
}
}
private IBaseService<TDbModel> GetBase<TDbModel>() where TDbModel : class
{
return new BaseService<TDbModel>();
}
public ICollection<TModel> GetAll()
{
ICollection<TModel> returnValue = new List<TModel>();
// This works!!!
foreach (var item in GetBase<Database.Categories>().GetAll())
{
returnValue.Add((TModel)(object)item);
}
baseService = DetermineDatabaseModel();
// This doesn't!!! It's the same thing!! :(
foreach (var item in baseService.GetAll())
{
returnValue.Add((TModel)(object)item);
}
return returnValue;
}
}
But remember, this not solve the issue You are facing. That is map 2 generic types.
Related
I have just begun exploring the design patterns and implementation of Web APIs.
I have a scenario where one single API requests to a set of APIs in sequence based on a string value.
Eg: let's say I have an API called StartAPI.
This might send request to a subset of APIs (let's call it API_X, API_Y, API_Z, API_T, API_U) based on given string.
Let's assume the below:
If i pass "string1" or "string2" to StartAPI then it should call API_X, API_Z.
If i pass "string3" it calls API_X, API_Z, API_T.
If i pass "string4" it calls all APIs
API_X, API_Z, API_T, API_Y, API_U.
What design pattern can I follow in this case to minimise the if else conditions?
It looks like that Chain of Responsibity pattern is way to go. As wiki says:
the chain-of-responsibility pattern is a behavioral design pattern
consisting of a source of command objects and a series of processing
objects.1 Each processing object contains logic that defines the
types of command objects that it can handle; the rest are passed to
the next processing object in the chain. A mechanism also exists for
adding new processing objects to the end of this chain.
So let me show an example how code would look like. Let's start from classes which define API:
public class BaseApi
{
public virtual string Get()
{
return "";
}
}
and its concrete implementations:
public class ApiX : BaseApi
{
public override string Get()
{
return "Api_X";
}
}
public class ApiZ : BaseApi
{
public override string Get()
{
return "Api_X";
}
}
public class ApiT : BaseApi
{
public override string Get()
{
return "Api_T";
}
}
Then this is Parameter class:
public class Parameter
{
public string Parameter_1 { get; set; }
}
Then we need some place where we will store all API's that should be called. I think, we can create some very simple factory. This factory will have just one overridable method:
public abstract class ApiSimpleFactory
{
public abstract IEnumerable<BaseApi> GetAll();
}
and its concrete implementations:
public class ApiXZSimpleFactory : ApiSimpleFactory
{
public override IEnumerable<BaseApi> GetAll() =>
new List<BaseApi>()
{
new ApiX(),
new ApiZ(),
};
}
public class ApiXZTSimpleFactory : ApiSimpleFactory
{
public override IEnumerable<BaseApi> GetAll() =>
new List<BaseApi>()
{
new ApiX(),
new ApiZ(),
new ApiT(),
};
}
Now, we are ready to implementat Chain Of Responsibity pattern:
public abstract class ApiHandler
{
private protected abstract IEnumerable<string> ParameterOptions { get; }
private ApiHandler _nextApiHandler;
public void SetSuccessor(ApiHandler nextVehicleHandler)
{
_nextApiHandler = nextVehicleHandler;
}
public virtual ApiSimpleFactory Execute(Parameter parameter)
{
if (_nextApiHandler != null)
return _nextApiHandler.Execute(parameter);
return null;
}
}
and its concrete implementations:
public class XZApiHandler : ApiHandler
{
private protected override IEnumerable<string> ParameterOptions =>
new List<string> { "string1", "string2" };
public override ApiSimpleFactory Execute(Parameter parameter)
{
if (ParameterOptions.Contains(parameter.Parameter_1))
return new ApiXZSimpleFactory();
return base.Execute(parameter);
}
}
public class XZTApiHandler : ApiHandler
{
private protected override IEnumerable<string> ParameterOptions =>
new List<string> { "string3" };
public override ApiSimpleFactory Execute(Parameter parameter)
{
if (ParameterOptions.Contains(parameter.Parameter_1))
return new ApiXZTSimpleFactory();
return base.Execute(parameter);
}
}
And now we can execute our code:
ApiHandler chain = new XZApiHandler();
ApiHandler xztApiHandler = new XZTApiHandler();
chain.SetSuccessor(xztApiHandler);
Parameter parameter = new Parameter { Parameter_1 = "string3" };
ApiSimpleFactory apiFactory = chain.Execute(parameter);
IEnumerable<BaseApi> apiToBeExecuted = apiFactory.GetAll();
The Data Access Layer is currently a repetition of 3 function: Create, Get, Set.
On a few Dlo type : Foo, Bar , FooBar.
Where Foo and FooBar have the same implementation and Bar has a more complexe one.
public static bool CreateFooBar(FooBarDlo newFooBar)
{
bool result = false;
using (var db = new FooModelDBcontext())
{
db.FooBars.Add(newFooBar);
result = db.SaveChanges() > 0;
}
return result;
}
public static FooBarDlo GetCustomer(int idFooBar)
{
FooBarDlo result;
using (var db = new FooModelDBcontext())
{
result = db.FooBars.FirstOrDefault(x => x.Id == idFooBar);
}
return result;
}
public static bool SetCustomer(FooBarDlo newFooBar)
{
bool result = false;
using (var db = new FooModelDBcontext())
{
var temp = db.FooBars.SingleOrDefault(x => x.Id == newFooBar.Id);
db.Entry(temp).CurrentValues.SetValues(newFooBar);
result = db.SaveChanges() > 0;
}
return result;
}
How can those be refactor, while keeping the specificities of the Bar implementation ?
There are several ways to go about it.
You could provide a base class that takes generics as a parameter with all virtual methods (pseudocode)
public abstract class DbLayer<T> {
public virtual T Get(int Id) {
// default implementation here
// but virtual allows overriding
}
public virtual T Create(T obj) {
// default implementation here
// but virtual allows overriding
}
}
public class FooBarDlo: DbLayer {
public override FooBarDlo Get(int Id) {
// override Get handling
}
}
But if I were you, I'd find a pre-built database layer on CodeProject and go with that.
What I'm trying to do is to instantiate a service using NInject and a route param.
I have something like this:
DAL
public interface IDALContract
{
object GetById(int id);
}
public class DALPeopleContract : IDALContract
{
public object GetById(int id)
{
//get person
return null;
}
}
public class DALAnimalsContract : IDALContract
{
public object GetById(int id)
{
//get animal
return null;
}
}
public static class DALContractFactory
{
public static IDALContract GetContract(int discriminator)
{
switch(discriminator)
{
case 1: return new DALPeopleContract();
case 2: return new DALAnimalsContract();
default: throw new NotSupportedException();
}
}
}
Business Layer
public interface IMyService
{
object GetById(int id);
}
public class MyService : IMyService
{
private IDALContract _contract;
public MyService(int discriminator)
{
_contract = DALContractFactory.GetContract(discriminator)
}
public object GetById(int id)
{
return _contract.GetById(id);
}
}
Controller
public class MyController
{
private IMyService _myService;
public MyController()
{
//how do I get the discriminator here? (the discriminator should be a route param)
IParameter param = new Parameter("MyParam", discriminator, true);
_myService = NInjectKernel.TryGet<IMyService>(param);
}
ActionResult Index(id)
{
_myService.GetById(id);
return View(model);
}
}
So the issue that I'm having is how to get the param, or is there a better approach to this. Basicaly what I'm trying to do is to have one controller that handles the same actions for different models, but I'm having an issue with the Data Access Layer (DAL).
Would it be a good idea to get the value on OnActionExecuting and instantiate there the service?
I found a clean (in my opinion) solution to my issue.
So now I have a fairly easy way to deal with simple operation on related classes.
I replaced the DALContractFactory with some NInject binding. And I have a custom route defined for my controller that requires a "type" that is read in OnActionExecuting on my controller.
For the models, I have a factory defined and a custom mapper (I haven't posted them here because they were not relevant to the question). If anybody is interested, I can post a sample sln with this approach.
So now I have something like:
DAL
public interface IDALContract
{
object GetById(int id);
}
public class DALPeopleContract : IDALContract
{
public object GetById(int id)
{
//get person
return null;
}
}
public class DALAnimalsContract : IDALContract
{
public object GetById(int id)
{
//get animal
return null;
}
}
Business Layer
public enum Discriminator
{
Animal,
Person
}
public interface IMyService
{
object GetById(int id);
}
public class MyService : IMyService
{
private IDALContract _contract;
public MyService(IDALContract contract)
{
_contract = contract;
}
public object GetById(int id)
{
return _contract.GetById(id);
}
}
Controller
public class MyController : Controller
{
private IMyService _myService;
protected override void OnActionExecuting(ActionExecutingContext ctx)
{
base.OnActionExecuting(ctx);
int type;
var routeValue = ControllerContext.RouteData.Values["type"];
Discriminator type;
if(!Enum.TryParse<Discriminator>(routeValue.ToString(), out type))
{
//set a default value
type = Discriminator.Animal;
}
_myService = NInjectKernel.Instance.GetService<IMyService>("type", type);
}
public ActionResult Index(id)
{
_myService.GetById(id);
return View(model);
}
}
NInjectConfiguration
public class NInjectKernel
{
private readonly IKernel _kernel;
private NInjectKernel()
{
_kernel = new StandardKernel();
}
private static volatile Irr2NInjectKernel _instance;
private static readonly object SyncRoot = new object();
public static Irr2NInjectKernel Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null)
{
var temp = new Irr2NInjectKernel();
temp.BindAllDependencies();
_instance = temp;
}
}
}
return _instance;
}
}
private void BindAllDependencies()
{
_kernel.Bind<IMyService>().To<MyService>();
_kernel.Bind<IDALContract>().ToMethod(x =>
{
IParameter parameter = x.Parameters.SingleOrDefault(p => p.Name == "type");
if (parameter != null)
{
var recordType = (Discriminator)parameter.GetValue(x, x.Request.Target);
switch (recordType)
{
case RecordType.Animal:
return new DALAnimalsContract();
case RecordType.Person:
return new DALPeopleContract();
default:
throw new NotSupportedException("DQS type is not suppported.");
}
}
throw new NotSupportedException();
});
}
}
I have just learned about GraphDiff, and how it is supposed to take care of all the differences between the disconnected entity and the one stored in the database.
The thing is that I do not know how to use GraphDiff, I tried the documentation, but I didn't understand it well.
I am using an abstracted DBContext, through an Interface and using DbSet so I could perform Unit Testing on them:
public interface IDbRepositories
{
IDbSet<Client> ClientsDB { get;}
AppIdentityDbContext DB { get; }
IDbSet<Contacts> ContactsDB { get; }
IDbSet<ExposureResult> ExposureDB { get; }
IDbSet<OrderMods> OrderModsDB { get; }
IDbSet<ProductDetails> ProductDetailsDB { get; }
IDbSet<OrderProcess> OrderProcessDB { get; }
IDbSet<Order> OrderDB { get; }
void SaveChanges();
}
This is the actual class implementing the interface:
public class DbRepositories : IDbRepositories
{
private AppIdentityDbContext db = new AppIdentityDbContext();
//Get DB Context. This is done this way, so a Mock can be injected when testing
public IDbSet<Client> ClientsDB
{
get { return db.Clients; }
}
public AppIdentityDbContext DB
{
get { return db; }
}
public IDbSet<Contacts> ContactsDB
{
get { return db.Contacts; }
}
public IDbSet<ExposureResult> ExposureDB
{
get { return db.ExposureTBL; }
}
public IDbSet<OrderMods> OrderModsDB
{
get { return db.OrderMods; }
}
public IDbSet<ProductDetails> ProductDetailsDB
{
get { return db.ProductDetailsTBL; }
}
public IDbSet<OrderProcess> OrderProcessDB
{
get { return db.OrderProcesses; }
}
public IDbSet<Order> OrderDB
{
get { return db.OrderTBL; }
}
public void SaveChanges()
{
this.db.SaveChanges();
}
}
Now, the problem part is in here:
public bool SaveOrderChanges(OrderProcess[] Order, int OrderID, int uid)
{
//2nd Step:
var ComparableObject = dbs.OrderProcessDB.Where(x => x.OrderID == OrderID).ToList();
var Objections = dbs.OrderDB.Where(x => x.OrderID == OrderID).FirstOrDefault();
dbs.DB.UpdateGraph(dbs.OrderDB, m => m.OwnedCollection());
dbs.SaveChanges();
return true;
}
I'd like to tell the differences between the Order parameter and the one I extract from OrderProcessDB. These are a One to Many Relationship.
I do not know how to use GraphDiff for this scenario. Any ideas?
You could just expose the base DbContext object in the interface, but that would violate basic principles of encapsulation. The challenge is that the UpdateGraph method is a static extension off of the concrete DbContext class. Here is my solution:
First the interface:
public interface IMyDbContext
{
...
TEntity UpdateGraph<TEntity>(TEntity entity, Expression<Func<IUpdateConfiguration<TEntity>, object>> mapping = null) where TEntity : class, new();
}
Then the actual DbContext:
public class MyDbContext : DbContext, IMyDbContext
{
...
public TEntity UpdateGraph<TEntity>(TEntity entity, Expression<Func<IUpdateConfiguration<TEntity>, object>> mapping = null) where TEntity : class, new()
{
return ((DbContext)this).UpdateGraph(entity, mapping);
}
}
And lastly example usage inside of a repository:
public class MyRepository : IMyRepository
{
private readonly IMyDbContext _myDbContext;
public MyRepository (IMyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
public async Task<SomeEntity> UpdateSomeEntity(SomeEntity updatedSomeEntity)
{
_myDbContext.UpdateGraph(updatedSomeEntity, map => map.OwnedCollection(p => p.SomeChildCollection));
await _myDbContext.SaveChangesAsync();
return updatedSomeEntity;
}
}
I realize this is old, but I just found out about GraphDiff and can hopefully help anyone else looking.
This is how you use GraphDiff:
db.UpdateGraph(orderToUpdate, map => map
.AssociatedCollection(t => t.Products)
.OwnedCollection(t => t.PaymentMethods));
This says to update the Order object, and that the Order owns the PaymentMethods (meaning it can actually remove those entities), and is associated with the Products entities (meaning it will remove them from the reference table).
Let's assume I have a class like
public class DataService
{
public IList<T> All<T>() { ... }
public T Get<T>(int id) { ... }
...
}
I could use it in various ways...
var dataService = new DataService();
var customers = dataService.All<Customer>();
var order = dataService.Get<Order>(1);
... but if I had a bunch of operations with the same T, this would become cumbersome. Then it would be nice to have something like this:
dataService.TypeIs<Order>();
var order2 = dataService.Get(2);
var order2 = dataService.Get(3);
var allOrders = dataService.All();
How would a TypeIs<T>() method look like? I think it had to somehow convert DataService to DataService<T> and set T... Or is this utterly impossible?
Yes, it's possible using a clever proxy:
public class DataService
{
public IList<T> All<T>() { ... }
public T Get<T>(int id) { ... }
...
}
public class DataServiceProxy<T>
{
public DataServiceProxy(DataService ds)
{
this.ds = ds;
}
public IList<T> All()
{
return this.ds.All<T>();
}
public T Get(int id)
{
return this.ds.Get<T>(id);
}
}
The equivalent of your dataService.TypeIs<Order>(); is var dataServiceProxy = new DataServiceProxy<Order>(dataService).