I'm overriding the ValidateEntity method to check for unique validation and I've hit a stumbling block.
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var result = new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
if (entityEntry.Entity is ReferenceType && entityEntry.State == EntityState.Added)
{
var entity = entityEntry.Entity as ReferenceType;
var pluralService = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-gb"));
var pluralEntity = pluralService.Pluralize(entity.GetType().Name);
// I would like Courses to be replaced with the property name of pluralEntity
if (Courses.Where(x => x.Title == entity.Title).Count() > 0)
{
result.ValidationErrors.Add(new DbValidationError(nameof(entity.Title), nameof(entity.Title) + " must be unique."));
}
}
if (result.ValidationErrors.Count > 0)
{
return result;
}
else
{
return base.ValidateEntity(entityEntry, items);
}
}
In my SchoolContext class I have the property DbSet<Course> Courses which is a ReferenceType (a custom abstract class type).
The value of pluralEntity is Courses, but I want to put in the if-statement something similar to:
if (Property(pluralEntity).Where(x => x.Title == entity.Title).Count() > 0)
{
// validate
}
Is there a way to do this?
Update
I've got this:
var prop = (DbSet<ReferenceType>) GetType().GetProperty(pluralEntity).GetValue(this, null);
if (prop.Where(x => x.Title == entity.Title).Count() > 0)
{
result.ValidationErrors.Add(new DbValidationError(nameof(entity.Title), nameof(entity.Title) + " must be unique."));
}
But because ReferenceType is an abstract class it cannot cast it at runtime.
I'd like to do something like this
var prop = (DbSet<typeof(entityEntry.Entity.GetType().Name)>)
But of course that's a variable and can't be passed in as a generic type
The only thing I can think of at the moment is writing a custom validation method, using the repository pattern.
First, create an interface which all your entities will implement
public interface IEntity
{
public string Title {get; set; }
}
Then create the repository:
public class Repository<TEntity> where TEntity: class, IEntity
{
private YourContext context = new YourContext();
private DbSet<TEntity> AppDbSet;
public Repository()
{
AppDbSet = context.Set<TEntity>();
}
//a couple of method to retrieve data...
public List<TEntity> GetAll()
{
return AppDbSet.ToList();
}
public IEnumerable<TEntity> Find(Func<TEntity, bool> predicate)
{
return AppDbSet.Where<TEntity>(predicate);
}
public TEntity Single(Func<TEntity, bool> predicate)
{
return AppDbSet.FirstOrDefault(predicate);
}
//Lastly, implement a validation method
public bool IsValid(TEntity entity)
{
if (AppDbSet.SingleOrDefault(x => x.Title == entity.Title) != null)
return false;
else
return true;
}
}
Use the repository as follow:
Repository<Course> courseRepository = new Repository<Course>();
Course course = new Course();
course.Title = "Boring course";
Console.WriteLine(courseRepository.IsValid(course));
Hope it helps.
Related
I have the following search function for the search for duplicate values
public bool isRecordExisting(string newValue)
{
bool isExisting = false;
using (var db = new SampleEntities_1())
{
var res = db.SAMPLE_TABLE.Where(x => x.SAMPLE_COLUMN == newValue).First();
if (res != null) {
isExisting = false;
}
}
return isExisting;
}
I got a few DbInstances
SampleEntities_1
SampleEntities_2
SampleEntities_3
Therefore I trying to make this function a generic one, like following
public bool isRecordExisting(string newValue, string column, DbSet<T> tableName, DbContext dbcontextname)
{
bool isExisting = false;
using (var db = new dbcontextname())
{
var res = db.tableName.Where(x=>x.column = newValue).First();
if (res != null)
{
isExisting = false;
}
}
return isExisting;
}
so I can call this function like this
var result = isRecordExisting("Bob", "SAMPLE_COLUMN", "SAMPLE_TABLE", SampleEntities_1);
can I know this approach possible or not, already I have compilation errors :(
'dbcontextname' is a variable but is used like a type
'SampleEntities_1' is a type, which is not valid in the given context
You could use a Generic repository, or a factory type pattern, etc..
Example, if you want to create a Generic Repository in your case, then something like this:
public class GenericRepo<TEntity, TContext> : IGenericRepo<TEntity>, IDisposable where TEntity : class where TContext : DbCOntext, new()
{
public TContext Context;
public GenericRepo(DbContext)
{
Context = dbContext as TContext;
}
public virtual TEntity Get(Expression<Func<TEntity, bool>> where = null)
{
Context.Set<TEntity>.FirstOrDefault(where);
}
}
Then maybe something like this:
public bool isRecordExisting(string newValue, string column)
{
bool isExisting = false;
using (var db = new GenericRepo<EntityType, SampleEntities_1>())
{
var res = db.Get(x => x.column == newValue);
if (res != null)
{
isExisting = false;
}
}
return isExisting;
}
Although you can pass the column and tablename essentially this way ^, you still need to create an instance of the GenericRepo for each DBContext. Same with the factory pattern. You could try what Salomon Zhang mentioned in the comments.
Also, note: Always use async code for accessing the DB.
How do I make this expression dynamic based on the generic type passed in the parameter?
In the simplified form:
public static class CompareService
{
public static List<T> Run<T>(List<T> database_list, string directory_path)
{
var csv_list = CompareService.MergeRecordsFromFiles<T>(directory);
return CompareService.RunComparison<T>(database_list, csv_list);
}
public static T CompareData<T>(List<T> database_list, List<T> csv_list)
{
var diff = new List<T>();
foreach (var db_item in database_list)
{
// ...
// if T is of type Deathstar compare reference_number property
// if T is of type Stormtrooper compare id property
// if T is of type Sith compare id and anger_level property
var csv_item = csv_list.FirstOrDefault(x => x.reference_number == db_item.reference_number);
// Comparison code
ComparisonResult result = compareLogic.Compare(db_item, csv_item);
// ...
}
return diff;
}
}
It is called from another generic service:
public static void Whatever<T>(List<T> list)
{
// ...
var directory_path = "C:\";
var delta = CompareService.CompareData<T>(list, directory_path);
// ...
}
The most naive implementation would be to check if your itemToFind can be cast to DeathStar, StormTrooper or Sith and if so call the instances property.
var deathStar = itemToFind as DeathStar;
if(deathStar != null)
return database_list.Where(x => ((DeathStar)x).reference_number == deathStar.reference_number).FirstOrDefault();
else
{
var sith = itemToFind as Sith;
if(sith != null)
return database_list.Where(x => ((Sith)x).anger_level == sith.anger_level).FirstOrDefault();
else
return database_list.Where(x => ((StormTrooper)x).id== ((StormTrooper)item).id).FirstOrDefault();
}
This is quite cumbersome, including many casts. In particular it completely bypasses the actual benefits of generics using any arbitrary type (that fullfills the constraints if existing). In your case you´d have a generic method that will only wortk for three decent types.
A better approach is to let all your classes implement a common interface that defines a property, for instance:
interface IObject {
int Level { get; }
}
Now all classes define that level-property:
clas DeathStar : IObject
{
public int Level { get { return this.reference_number; } }
}
clas Sith : IObject
{
public int Level { get { return this.anger_level; } }
}
clas StormTrooper: IObject
{
public int Level { get { return this.id; } }
}
Than you can use a constraint on your type T to implement that interface:
public static T CompareData<T>(List<T> list, T itemToFind) where T: IObject
Why not like this:
public static T CompareData<T>(List<T> list, Func<T, bool> predicate)
{
return database_list.FirstOrDefault(predicate);
}
And then use it like this:
var itemToFind = new ItemToFind();
var myObjectList = new List<MyObject>();
var item = CompareData<MyObject>(myObjectList, x=> x.MyObjectProperty == itemToFind.Id);
You could add a property selector:
public static class CompareService
{
public static T CompareData<T>(this List<T> list, T itemToFind, Func<T, int> propSelector)
{
int propToFind = propSelector(itemToFind); // cache
return database_list.FirstOrDefault(x => propSelector(x) == propToFind);
}
}
And call it like that:
listOfDeathstars.CompareData(deathStarToFind, ds => ds.reference_number);
listOfStormtroopers.CompareData(trooperToFind, t => t.id);
listOfSiths.CompareData(sithStarToFind, sith => new { sith.id, sith.anger_level});
Note: I added the this keyword in the signature to make it an extension (not sure if you intended that but forgot the keyword). And Where(predicate).FirstOrDefault() can be reduced to FirstOrDefault(predicate).
I have a extension method that checks the object for its type and then populate its member property
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository)
where T: MyEntity
{
var agenda = entity as Agenda;
if (agenda != null)
{
agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
}
var participant = entity as Participant;
if (participant != null)
{
participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
}
}
can I further refactor that to something like this to make it more generic?
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T : MyEntity
{
var obj = entity as Agenda || entity as Participant;
if (obj != null)
{
obj.Meeting = meetingRepository.GetMeetingById(obj.MeetingId);
}
}
}
PS: I don't want to put the object's property Meeting in the Base class (MyEntity)
I would, personally, just use overloads:
public static void LoadMeeting(this Agenda agenda, IMeetingRepository meetingRepository)
{
if (agenda != null)
{
agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
}
}
public static void LoadMeeting(this Participant participant, IMeetingRepository meetingRepository)
{
if (participant != null)
{
participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
}
}
You couldn't do it with a single generic method unless you had some shared contract (either a base class or interface implemented) which provided the Meeting property.
The alternative would be to make a shared interface, ie: IMeeting, then constrain to that:
public interface IMeeting
{
public Meeting Meeting { get; set; }
public int MeetingId { get; }
}
Then you can write:
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository)
where T: IMeeting
{
if (entity != null)
{
entity.Meeting = meetingRepository.GetMeetingById(entity.MeetingId);
}
}
As you're using EF, you could implement this interface in a partial class:
public partial class Agenda : MyEntity, IMeeting
{
}
You may want to return early out of the method incase you have to handle a class and it's base class.
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T: MyEntity
{
var agenda = entity as Agenda;
if (agenda != null)
{
agenda.Meeting = meetingRepository.GetMeetingById(agenda.MeetingId);
return;
}
var participant = entity as Participant;
if (participant != null)
{
participant.Meeting = meetingRepository.GetMeetingById(participant.MeetingId);
return;
}
}
You might also consider a table approach:
public static void LoadMeeting<T>(this T entity, IMeetingRepository meetingRepository) where T: MyEntity {
var name = entity.GetType().Name;
if (Table.ContainsKey(name)) {
Table[name](entity, meetingRepository);
}
}
Where Table is:
static Dictionary<String, Action<MyEntity, IMeetingRepository>> Table = new Dictionary<String, Action<MyEntity, IMeetingRepository>>();
And it is initialized like so:
Table.Add("Agenda", (agenda, meetingRepository) => {
((Agenda)agenda).Meeting = meetingRepository.GetMeetingById(((Agenda)agenda).MeetingId); });
Table.Add("Participant", (participant, meetingRepository) => {
((Participant)participant).Meeting = meetingRepository.GetMeetingById(((Participant)participant).MeetingId); });
Obviously your Table will have to be static and available to your extension method (say in the containing class).
This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 8 years ago.
Given the following Interfaces:
interface IEntity
{
int Id{get;}
}
interface IPerson : IEntity
{
string Name{get;}
int Age{get;}
}
interface ITeacher : IPerson
{
string StaffId{get;}
}
interface IStudent : IPerson
{
string StudentId{get;}
string Courses{get;}
}
interface IRepository
{
T Get<T>(int id) where T : IEntity
}
I have the following classes in my namespace
public class EntityBase() : IEntity
{
int Id{get;set;}
}
public class Teacher : EntityBase, ITeacher{}
public class Sudent : EntityBase, IStudent{}
Currently I am implementing this IRepository as follows:
class Repository: IRepository
{
IDataContext Context{get;set;}
T Get<T>(int id) where T : EntityBase
{
if(typeof(T) == typeof(Teacher))
return Context.Get<ITeacher>(id);
if(typeof(T) == typeof(Sudent))
return Context.Get<ISudent>(id);
throw new Exception("Unknown Interface " + typeof(T).Name);
}
}
Is there a betterway of implementing this? Given that our Context has no knowledge of our data types (Teacher, Student), just its interfaces (ITeacher, IStudent).
Can something like this work?
class Repository: IRepository
{
T Get<T>(int id) where T : EntityBase
{
var MyInterface = FindInterface<T>();
return Context.Get<MyInterface>(id);
}
}
I think this will do:
class Repository: IRepository
{
IDataContext Context{get;set;}
T Get<T>(int id) where T : EntityBase
{
string[] interfaceList = new string[]
{ "ITeacher", "IStudent"};
Type interfaceType = null;
foreach (string s in interfaceList)
{
var types = typeof(T).FindInterfaces((x, y) => x.Name == y.ToString(), s);
if (types.Length > 0)
interfaceType = types[0];
}
if (interfaceType == null)
throw new Exception("Unknown Interface " + typeof(T).Name);
MethodInfo method = typeof(Context).GetMethod("Get");
MethodInfo generic = method.MakeGenericMethod(interfaceType);
var returnValue = generic.Invoke(Context, new object[] { id });
return (T)Convert.ChangeType(returnValue, typeof(T));
}
}
EDIT: As I don't know the name of your namespace, I have used the Name property to filter the interfaces. In real world usage I will suggest that you use FullName just to be sure, like this:
...
string[] interfaceList = new string[]
{ "MyNamespace.ITeacher", "MyNamespace.IStudent"};
...
var types = typeof(T).FindInterfaces((x, y) => x.FullName == y.ToString(), s);
I think you can accomplish this through reflection by finding the Get method on Context class, and invoking it as a generic call for the caller-supplied type T. I haven't tested this, but the code should look something like this:
T Get<T>(int id) where T : EntityBase
{
Type context = Context.GetType();
MethodInfo getMethod = context.GetMethod("Get", BindingFlags.Public);
MethodInfo genericGet = getMethod.MakeGenericMethod(new [] {typeof(T)});
return (T)genericGet.Invoke(Context, new object[] { id } );
}
It looks to me like you mean it the other way around. You don't want to pass interface types to Context.Get<>, do you?
// is this what you mean?
if (typeof(T) == typeof(ITeacher))
return Context.Get<Teacher>(id);
If it is, you'll need to use MakeGenericMethod, see this for an example (note the caching part).
If it is not, you might be misunderstanding some concepts of LINQ and/or Repository pattern.
However I'm curious why did you decide to use interfaces. LINQ objects are POCO anyways, why adding another layer of abstraction which involves (grrsh!) calling generic methods on DataContext via reflection?
A simple return Context.Get<T>(id) could be accomplished as following:
class Repository : IRepository
{
public IDataContext Context { get; set; }
public T Get<T>(int id) where T : IEntity, new()
{
return Context.Get<T>(id);
}
}
Following is your object/interface model with implementation for the Context
interface IEntity
{
int Id{get;}
}
interface IPerson : IEntity
{
}
interface ITeacher : IPerson
{
}
interface IStudent : IPerson
{
}
interface IDataContext
{
T Get<T>(int id) where T:new();
}
interface IRepository
{
T Get<T>(int id) where T : IEntity , new() ;
}
public class EntityBase : IEntity
{
public virtual int Id{get;set;}
}
public class Teacher : EntityBase, ITeacher {
int id=0;
public override int Id {
get { return this.id; }
set { this.id = value; }
}
}
public class Student : EntityBase, IStudent
{
int id=0;
public override int Id {
get { return this.id; }
set { this.id = value; }
}
}
class Context<T>: IDataContext where T: EntityBase, new()
{
ArrayList store;
public Context(int dataSize)
{
store = new ArrayList(dataSize);
for (int i = 0; i < dataSize; i++)
{
T t = new T();
t.Id = i;
store.Add(t);
}
}
public T Get<T>(int i) where T:new()
{
if (i<store.Count)
{
return (T)store[i];
}
else
{
return default(T);
}
}
}
Now finally the main method class to demonstrate that it all hangs together nicely.
using System;
using System.Collections;
class MyClass
{
static void Main(string[] args)
{
Context<Teacher> teachersContext = new Context<Teacher>(100);//contructs a db of 100 teachers
Context<Student> studentsContext = new Context<Student>(100);//contructs a db of 100 teachers
Repository repo = new Repository();
// set the repository context and get a teacher
repo.Context = teachersContext;
Teacher teacher1 = repo.Get<Teacher>(83); //get teacher number 83
Console.WriteLine("Teacher Id:{0} ", teacher1.Id);
// redirect the repositry context and now get a student
repo.Context = studentsContext;
Student student1 = repo.Get<Student>(35); //get student number 35
Console.WriteLine("Student Id: {0} ", student1.Id);
Console.ReadLine();
}
I wrote a class that allows a derivate to specify which of its properties can be lazy loaded. The code is:
public abstract class SelfHydratingEntity<T> : DynamicObject where T : class {
private readonly Dictionary<string, LoadableBackingField> fields;
public SelfHydratingEntity(T original) {
this.Original = original;
this.fields = this.GetBackingFields().ToDictionary(f => f.Name);
}
public T Original { get; private set; }
protected virtual IEnumerable<LoadableBackingField> GetBackingFields() {
yield break;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
result = field.GetValue();
return true;
} else {
var getter = PropertyAccessor.GetGetter(this.Original.GetType(), binder.Name);
result = getter(this.Original);
return true;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
field.SetValue(value);
return true;
} else {
var setter = PropertyAccessor.GetSetter(this.Original.GetType(), binder.Name);
setter(this.Original, value);
return true;
}
}
}
And a derivate class:
public class SelfHydratingPerson : SelfHydratingEntity<IPerson> {
private readonly IDataRepository dataRepository;
public SelfHydratingDerivate(IDataRepository dataRepository, IPerson person)
: base(person) {
this.dataRepository = dataRepository
}
protected override IEnumerable<LoadableBackingField> GetBackingFields() {
yield return new LoadableBackingField("Address", () => this.dataRepository.Addresses.Get(this.Original.AddressID));
}
}
This works perfectly fine for getting and settings property values, but I get a either a RuntimeBinderException when I implicitly cast or an InvalidCastException with an explicitly cast SelfHydratingEntity back to T.
I know that you can override the DynamicObject.TryConvert method, but I'm wondering what exactly to put in this method. I've read a lot about duck typing today, and have tried out several libraries, but none of them work for this particular scenario. All of the libraries I've tried today generate a wrapper class using Reflection.Emit that makes calls to "get_" and "set_" methods and naturally use reflection to find these methods on the wrapped instance. SelfHydratingEntity of course doesn't have the "get_" and "set_" methods defined.
So, I'm wondering if this kind of thing is even possible. Is there any way to cast an instance of SelfHydratingEntity to T? I'm looking for something like this:
var original = GetOriginalPerson();
dynamic person = new SelfHydratingPerson(new DataRepository(), original);
string name = person.Name; // Gets property value on original
var address = person.Address; // Gets property value using LoadableBackingField registration
var iPerson = (IPerson)person;
- or -
var iPerson = DuckType.As<IPerson>(person);
Have you seen this Duck Typing project. It looks pretty good. I have just found a great example from Mauricio. It uses the Windsor Castle dynamic proxy to intercept method calls
Using the code from Mauricio the following code works like a dream
class Program
{
static void Main(string[] args)
{
dynamic person = new { Name = "Peter" };
var p = DuckType.As<IPerson>(person);
Console.WriteLine(p.Name);
}
}
public interface IPerson
{
string Name { get; set; }
}
public static class DuckType
{
private static readonly ProxyGenerator generator = new ProxyGenerator();
public static T As<T>(object o)
{
return generator.CreateInterfaceProxyWithoutTarget<T>(new DuckTypingInterceptor(o));
}
}
public class DuckTypingInterceptor : IInterceptor
{
private readonly object target;
public DuckTypingInterceptor(object target)
{
this.target = target;
}
public void Intercept(IInvocation invocation)
{
var methods = target.GetType().GetMethods()
.Where(m => m.Name == invocation.Method.Name)
.Where(m => m.GetParameters().Length == invocation.Arguments.Length)
.ToList();
if (methods.Count > 1)
throw new ApplicationException(string.Format("Ambiguous method match for '{0}'", invocation.Method.Name));
if (methods.Count == 0)
throw new ApplicationException(string.Format("No method '{0}' found", invocation.Method.Name));
var method = methods[0];
if (invocation.GenericArguments != null && invocation.GenericArguments.Length > 0)
method = method.MakeGenericMethod(invocation.GenericArguments);
invocation.ReturnValue = method.Invoke(target, invocation.Arguments);
}
}
impromptu-interface
https://github.com/ekonbenefits/impromptu-interface
Can static cast interfaces onto objects derived from DynamicObject.