none
Generic methods to access EF6 data RRS feed

  • Question

  • I am trying to implement a data layer which can support different underlying datastores (eg like Repository)
    It works fine when I do not use generics (ie separate functions in each class) but generics would be much more flexible.

    The classes are pretty bog standard, Account, Customer, Supplier etc with the sort of properties you would expect. 
    They work fine when used directly with EF6

     Below are my business side methods

     public virtual void Add<E>(E entity) where E : class { }
            public virtual void Remove<E>(E entity) where E : class { }
            public virtual int Count<E>() where E : class { return 0; }
            public virtual List<E> List<E>() where E : class { return null; }
            public virtual IQueryable<E> Find(Expression<Func<E, bool>> predicate) { return null;}

    and here are the Data side for EF6

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Data.Entity;
    using System.Linq.Expressions;

            public override void Add<E>(E entity){ctx.Entry(entity).State = EntityState.Added;}
            public override void Remove<E>(E entity){ctx.Entry(entity).State = EntityState.Deleted;}
            public override int Count<E>(){DbSet<E> DbSet = ctx.Set<E>();return DbSet.Count();}
            public override List<E> List() {DbSet<E> DbSet = ctx.Set<E>();return DbSet.ToList();}
            public override IQueryable<E> Find<E>(Expression<Func<E, bool>> predicate){DbSet<E> DbSet = ctx.Set<E>();return DbSet.Where(predicate);}

    ctx is the EF6 DataContext.
    The Add, Remove, Count and List work OK, but I am struggling with Find, Visual studio gives errors for the generic types <E>
    "The type E must be a Reference type".   It is, it is just a normal class

    The Find code I discovered on the web, but it does not work for me (nor do I fully understand it!)

    What should the Find be, or any comments on the others?


    John Meers


    • Edited by JohnMeers Tuesday, March 22, 2016 9:16 PM
    • Moved by Kristin Xie Wednesday, March 23, 2016 3:12 AM
    Tuesday, March 22, 2016 8:49 PM

Answers

  • Hi JohnMeers,

    When you define a generic class, you can apply restrictions to the kinds of types that client code can use for type arguments when it instantiates your class. If client code tries to instantiate your class by using a type that is not allowed by a constraint, the result is a compile-time error. These restrictions are called constraints. So I suspect that the code as below cause the issue.

    public virtual IQueryable<E> Find(Expression<Func<E, bool>> predicate) { return null;}

    please try to modify the code snippet above like below and check if it works for you.

    public virtual IQueryable<E> Find(Expression<Func<E, bool>> predicate) where E : class { return null;}

    For more information about this, please see:

    https://msdn.microsoft.com/en-us/library/d5x73970.aspx

    Best regards,

    Cole Wu


    Wednesday, March 23, 2016 6:54 AM
    Moderator

All replies

  • Hi JohnMeers,

    This forum is about the C# programming language, IDE, libraries, samples, and tools, as your issue is more related to the entity framework programming, we help you move it to the ADO.NET Entity Framework and LINQ to Entities forum for better support.

    Thank you for your understanding.

    Best Regards,

    Albert Zhang

    Wednesday, March 23, 2016 3:07 AM
  • Hi JohnMeers,

    When you define a generic class, you can apply restrictions to the kinds of types that client code can use for type arguments when it instantiates your class. If client code tries to instantiate your class by using a type that is not allowed by a constraint, the result is a compile-time error. These restrictions are called constraints. So I suspect that the code as below cause the issue.

    public virtual IQueryable<E> Find(Expression<Func<E, bool>> predicate) { return null;}

    please try to modify the code snippet above like below and check if it works for you.

    public virtual IQueryable<E> Find(Expression<Func<E, bool>> predicate) where E : class { return null;}

    For more information about this, please see:

    https://msdn.microsoft.com/en-us/library/d5x73970.aspx

    Best regards,

    Cole Wu


    Wednesday, March 23, 2016 6:54 AM
    Moderator
  • Thanks Albert.

    I chose this forum as I suspected the issue was due to my not understanding the Generic functionally in C# properly - and it was!!

    However I see what you mean, in that this forum is for problems with the language itself.

    I imagine you must have hit this problem many times!!


    John Meers

    Wednesday, March 23, 2016 10:12 AM
  • That was it!!  Thanks.

    I was confused by slavishly copying code I did not fully understand.  When I now look back at the original I see the constraint was established elsewhere, not in the code I used.

    Still I should have spotted it myself.


    John Meers

    Wednesday, March 23, 2016 10:15 AM