0

I am trying to build a generic repo and have some issues. I have the following interface:

public interface IGenRepo<T, TKey> where T : class
{
    IQueryable<T> Items { get; }
    T find(TKey pk);
    RepoResult delete(TKey pk);
    RepoResult create(T item);
    RepoResult update(T item);
    RepoResult save();
}

And here is the class that implements that interface:

public class EFGenRepo<T, TKey> : IGenRepo<T, TKey> where T : class
{
    private PortalEntities context = new PortalEntities();

    public IQueryable<T> Items { get { return context.Set<T>().AsQueryable<T>(); } }

    public T find(TKey pk){}

    public RepoResult delete(TKey pk){}

    public RepoResult create(T item){
        if (item == null) return RepoResult.Failed(RepoMessages.paramIsNull());
        if (true) {//HELP HERE PLEASE, something like: if(item.PKHasNoValue == true)
            context.Set<T>().Add(item);
            return save();
        } else {
            return RepoResult.Failed(RepoMessages.PKIsNotZeroAtCreate());
        }
    }
    public RepoResult update(T item){}

    public RepoResult save(){
        try {
            context.SaveChanges();
            return new RepoResult();
        } catch (Exception e){
            return RepoResult.Failed(RepoMessages.saveChangesFailure(e));
        }
    }

    private RepoResult save(T item){}
}

In my create method i want to check the PK value of the item passed to the method. I know I can check this in my controller before calling the code but I want to do it like this! So, lets say I have a student class like below:

public partial class student
{       
    public int id { get; set; }
    public string naam { get; set; }
}

And pas a student object with an id of 0, now I want the if statement to evaluate to true. If the student object has an id already it must evaluate to false. But how can I check this. I guess I have to use something like the code below but I have no skills for that:

typeof(TKey).Name;
item.GetType().Name;

Any help is greatly appreciated!

Kip ei
  • 479
  • 6
  • 20

1 Answers1

0

The solution I made is creating an interface:

public interface IPKProvider
{
    bool PKHasNoValue();
}

I let all my auto-generated EF classes(student was just an example) implement this interface(in a seperate partial class file)

So the seperate student class looks like this:

public partial class schakeling : IPKProvider
{
    public bool PKHasNoValue() {
        return this.id == 0;
    }
}

Another EF entity, lets say, user will look like this:

public partial class user: IPKProvider
{
    public bool PKHasNoValue() {
        return string.IsNullOrEmpty(this.username);
    }
}

Now I can implement the IPKProvider interface in my EFGenRepo class like this:

public class EFGenRepo<T, TKey> : IGenRepo<T, TKey> where T : class, IPKProvider
{
    private PortalEntities context = new PortalEntities();

    public IQueryable<T> Items { get { return context.Set<T>().AsQueryable<T>(); } }

    public T find(TKey pk){}

    public RepoResult delete(TKey pk){}

    public RepoResult create(T item){
        if (item == null) return RepoResult.Failed(RepoMessages.paramIsNull());
        if (item.PKHasNoValue()) {//<----------PROBLEM SOLVED
            context.Set<T>().Add(item);
            return save();
        } else {
            return RepoResult.Failed(RepoMessages.PKIsNotZeroAtCreate());
        }
    }
    public RepoResult update(T item){}

    public RepoResult save(){
        try {
            context.SaveChanges();
            return new RepoResult();
        } catch (Exception e){
            return RepoResult.Failed(RepoMessages.saveChangesFailure(e));
        }
    }

    private RepoResult save(T item){}
}

This approach works, but it has some cons. Aldo not a lot of work I have to manually build an extra partial class for each auto generated EF entity. I also have too update them manually if the DB structure changes in the future(which doesn't happen a lot of course). It works but I just don't like it this way. Any comments would be appreciated.

Kip ei
  • 479
  • 6
  • 20