LINQ查询在通用存储库中,LINQ to Entities无法识别该方法

时间:2012-11-26 17:19:02

标签: c# linq entity-framework-4 repository-pattern

我正在我的应用程序中设置一个通用存储库,我遇到了一些LINQ查询的麻烦。

使用非通用的,我会这样做:

    private IObjectSet<T> _objectSet;

    public List<int?> GetGroups()
    {
        List<object> objectGroups = new List<object>();
        List<int?> intGroups = new List<int?>();

        var r = (from n in _objectSet
                 select n.Group_ID).Distinct();

        objectGroups = r.OrderBy(n => n.Value).ToList();

        foreach (object value in objectGroups)
        {
            intGroups.Add((int?)value);
        }

        return intGroups;

    }

由于这是 T 类型的通用类型,因此在输入“n。”时,IntelliSense不列出任何选项,因为 n 没有明确定义(对吧?)。

所以这就是我到目前为止所拥有的:

public interface IRepository<T> : IDisposable where T : class
{

    IQueryable<T> Fetch();
    IEnumerable<T> GetAll();
    IEnumerable<T> GetAll(bool activeOnly);
    IEnumerable<T> GetAll(string groupID, bool activeOnly);
    IEnumerable<T> Find(Func<T, bool> predicate);
    T Single(Func<T, bool> predicate);
    T First(Func<T, bool> predicate);
    List<int?> GetGroups();
    int Add(T entity);
    void Delete(T entity);
    void Attach(T entity);
    void SaveChanges();
    void SaveChanges(SaveOptions options);
}

public class DataRepository<T> : IRepository<T> where T : class
{



    /// <summary>
    /// The context object for the database
    /// </summary>
    private ObjectContext _context;

    private IEnumerable<T> _previousEntries;
    private string _PKName;

    /// <summary>
    /// The IObjectSet that represents the current entity.
    /// </summary>

    private IObjectSet<T> _objectSet;

    public DataRepository()
    {

        switch (typeof(T).Name)
        {
            case "CRM_Patient":
                _context = new TheseEntities();
                _PKName = "key_patient";
                break;
            case "CRM_Account":
                _context = new ThoseEntities();
                _PKName = "accountnumber";
                break;
            case "CRM_Supplier":
                _context = new OtherEntities();
                _PKName = "supplierid";
                break;
            default:
                _context = new OtherEntities();
                break;
        }

        _objectSet = _context.CreateObjectSet<T>();
        _previousEntries = this.GetAll();
    }

    /// <summary>
    /// Gets all records as an IQueryable
    /// </summary>
    /// <returns>An IQueryable object containing the results of the query</returns>

    public IQueryable<T> Fetch()
    {
        return _objectSet;
    }


    /// <summary>
    /// Gets all records as an IEnumberable
    /// </summary>
    /// <returns>An IEnumberable object containing the results of the query</returns>

    public IEnumerable<T> GetAll()
    {
        return Fetch().AsEnumerable();
    }

    /// <summary>
    /// Finds a record with the specified criteria
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>
    /// <returns>A collection containing the results of the query</returns>
    public IEnumerable<T> Find(Func<T, bool> predicate)
    {
        return _objectSet.Where<T>(predicate);
    }

    public List<int?> GetGroups()
    {
        List<object> objectGroups = new List<object>();
        List<int?> intGroups = new List<int?>();

        //var r = (from n in _objectSet
        //         select n.GetType().GetProperty("Group_ID").GetValue(n, null)).Distinct();


        var r = Fetch().Select(n => n.GetType().GetProperty("Group_ID").GetValue(n, null)).Distinct();

        objectGroups = r.OrderBy(n => n.GetType().GetProperty("Value").GetValue(n, null)).ToList();

        foreach (object value in r)
        {
            intGroups.Add((int?)value);
        }

        return intGroups;

    }
    /// <summary>
    /// Gets a single record by the specified criteria (usually the unique identifier)
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>
    /// <returns>A single record that matches the specified criteria</returns>
    public T Single(Func<T, bool> predicate)
    {
        return _objectSet.Single<T>(predicate);
    }

    /// <summary>
    /// The first record matching the specified criteria
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>

    /// <returns>A single record containing the first record matching the specified criteria</returns>
    public T First(Func<T, bool> predicate)
    {
        return _objectSet.First<T>(predicate);
    }



    /// <summary>
    /// Deletes the specified entitiy
    /// </summary>
    /// <param name="entity">Entity to delete</param>
    /// <exception cref="ArgumentNullException"> if <paramref name="entity"/> is null</exception>
    public void Delete(T entity)
    {
        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }

        _objectSet.DeleteObject(entity);
    }



    /// <summary>
    /// Deletes records matching the specified criteria
    /// </summary>
    /// <param name="predicate">Criteria to match on</param>
    public void Delete(Func<T, bool> predicate)
    {
        IEnumerable<T> records = from x in _objectSet.Where<T>(predicate) select x;
        foreach (T record in records)
        {
            _objectSet.DeleteObject(record);
        }
    }

    /// <summary>
    /// Dispose
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }



    /// <summary>
    /// Dispose
    /// </summary>
    /// <param name="disposing">A boolean value indicating whether or not to dispose managed resources</param>
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }

}

不知何故,我的反射技巧似乎是在LINQ语句中执行的,当我为objectGroups赋值时,这显然会导致抛出异常。

LINQ to Entities无法识别方法'System.Object GetValue(System.Object,System.Object [])'方法,并且此方法无法转换为商店表达式。

有什么想法吗?我真的需要保留存储库的通用性质。我正在使用Reflection的所有方法都抛出异常...

非常感谢。

编辑:添加了大部分Repository的方法和界面。类中可能缺少某些方法,但这样做是为了减轻阅读:)

1 个答案:

答案 0 :(得分:2)

如何在接口中定义ValueGroupID属性,然后让您的实体实现此接口并将其添加为通用约束?

然后,您的GetGroups方法将能够在不反射的情况下调用这些属性。