Generics 为什么我能';你不能让这个通用存储库正常工作吗?怎么了?

Generics 为什么我能';你不能让这个通用存储库正常工作吗?怎么了?,generics,c#-4.0,repository,Generics,C# 4.0,Repository,我有这个通用存储库 /// <summary> /// Implémentation de base d'un dépositoire pour Entity Framework. /// </summary> /// <remarks>Entity Framework 4.1</remarks> /// <typeparam name="TEntite">Entité spécifique.</typeparam> pu

我有这个通用存储库

 /// <summary>
/// Implémentation de base d'un dépositoire pour Entity Framework.
/// </summary>
/// <remarks>Entity Framework 4.1</remarks>
/// <typeparam name="TEntite">Entité spécifique.</typeparam>
public abstract class RepositoryBase<TEntity, TKey> : IRepository<TEntity>, IDisposable
    where TEntity : EntityBase<TKey>
    where TKey : class
{
    private readonly IContext _context;
    private ObjectContext _objectContext;
    private IObjectSet<TEntity> _objectSet;

    protected RepositoryBase(IContext context)
    {
        _context = context;
        _objectContext = _context.GetObjectContext();
        _objectSet = _objectContext.CreateObjectSet<TEntity>();
    }

    /// <see cref="IRepository.cs"/>
    public IEnumerable<TEntity> GetAll(Expression<Func<TEntity, object>> sortExpression)
    {
        if (sortExpression == null)
            sortExpression = x => x.Id;
        return _objectSet.OrderBy(sortExpression).AsEnumerable();
    }

    /// <see cref="IRepository.cs"/>
    public IEnumerable<TEntity> GetAll(int maximumRows, int startRowIndex, Expression<Func<TEntity, object>> sortExpression)
    {
        if (sortExpression == null)
            sortExpression = x => x.Id;
        return _objectSet.OrderBy(sortExpression).Skip(startRowIndex).Take(maximumRows).AsEnumerable();
    }

    /// <see cref="IRepository.cs"/>
    public TEntity SelectByKey(TKey key) 
    {
        if (key == null)
            throw new ArgumentNullException("La clé était NULL! Une clé est nécessaire pour récupérer un entité.");
        return _objectSet.SingleOrDefault(x => x.Id == key);
    }
//
///实体框架基础的实施。
/// 
///实体框架4.1
///全部指定。
公共抽象类RepositoryBase:IRepository,IDisposable
其中tenty:EntityBase
TKey在哪里:类
{
私有只读IContext\u上下文;
私有对象上下文_ObjectContext;
私有IObjectSet\u对象集;
受保护的RepositoryBase(IContext上下文)
{
_上下文=上下文;
_objectContext=_context.GetObjectContext();
_objectSet=_objectContext.CreateObjectSet();
}
/// 
公共IEnumerable GetAll(表达式sortExpression)
{
if(sortExpression==null)
sortExpression=x=>x.Id;
返回_objectSet.OrderBy(sortExpression.AsEnumerable();
}
/// 
公共IEnumerable GetAll(int-maximumRows、int-startRowIndex、Expression-sortExpression)
{
if(sortExpression==null)
sortExpression=x=>x.Id;
return _objectSet.OrderBy(sortExpression).Skip(startRowIndex).Take(maximumRows).AsEnumerable();
}
/// 
公共TEntity SelectByKey(TKey)
{
if(key==null)
抛出新的ArgumentNullException(“La clétait NULL!Une cléest nécessaire pour récupérer un entité”);
返回_objectSet.SingleOrDefault(x=>x.Id==key);
}
这里是具体的实现

公共类ProductRepository:RepositoryBase,IPProductRepository { 公共产品存储库(IContext上下文) :基本(上下文) { }
//
公共产品GetByName(字符串名称)
{
返回base.First(x=>x.Name==Name);
}
/// 
公共IEnumerable FindProduct(规范)
{
抛出新系统。NotImplementedException();
}
}
当我创建一个特定的存储库时..它说Tkey必须是一个引用类型,但为什么?有没有办法让这个通用存储库工作?Tkey是用来让SelectByKey方法接受一个键类型的

编辑#1:

如果删除约束,则会出现另一个问题…在SelectByKey方法中,无法使用==作为lambda表达式将TKey与TKey进行比较

编辑#2:

尝试使用Equals,语法似乎还可以

编辑#3:

Equals在运行时崩溃..说Tkey(似乎是一个System.Object)不能使用Equals,因为Object有equal方法,所以Equals看起来不逻辑。我目前没有访问真实代码的权限,但我用下面的代码做了一些测试

class Program
{
    static void Main(string[] args)
    {
        Test<TestEntity, int> t = new Test<TestEntity, int>();  
        t.TestMethod(5);
    }
}

class Test<TEntity, TKey>
    where TEntity : Entity<TKey>
{
    public Test()
    { }

    public TestEntity TestMethod(TKey id)
    {
        List<TestEntity> testEntity = new List<TestEntity>();
        testEntity.Add(new TestEntity(5));
        return testEntity.SingleOrDefault(x => x.Id.Equals(id));
    }
}

class Entity<TKey>
{
    public TKey Id { get; set; }
}

class TestEntity : Entity
{
    public TestEntity(int id)
    {
        Id = id;
    }
}

class Entity : Entity<int>
{
}
类程序
{
静态void Main(字符串[]参数)
{
测试t=新测试();
t、 试验方法(5);
}
}
课堂测试
其中tenty:实体
{
公开考试()
{ }
公共测试实体测试方法(TKey id)
{
List testEntity=新列表();
增加(新的测试(5));
返回testEntity.SingleOrDefault(x=>x.Id.Equals(Id));
}
}
类实体
{
公钥Id{get;set;}
}
类测试实体:实体
{
公共测试实体(内部id)
{
Id=Id;
}
}
类实体:实体
{
}
看来效果不错,所以我今晚晚些时候再试试

编辑#4

好的,我得到的例外是不能创建一个“System.Object”类型的常量值。这个上下文只支持主要类型,如int32、string和guid

它说Tkey必须是引用类型,但为什么

您有以下限制:

其中TKey:class


您需要约束吗?您希望支持哪些键类型?

在您的存储库声明中

public abstract class RepositoryBase<TEntity, TKey> : IRepository<TEntity>, IDisposable
    where TEntity : EntityBase<TKey>
    where TKey : class
{
公共抽象类RepositoryBase:IRepository,IDisposable
其中tenty:EntityBase
TKey在哪里:类
{
您已指定仅允许引用类型的类约束。请参阅

T:在哪里上课

类型参数必须是引用类型,包括任何类, 接口、委托或数组类型。(请参见下面的注释。)

删除:class约束以允许任何类型

除非您正在进行学习练习,否则我不会尝试从头开始构建您的存储库。我会利用其他人所做的工作。当我编写存储库框架时,我需要一个GetById方法,该方法可以处理各种类型的主键(尽管不是多列主键).在写这篇文章时,我发现以下两篇文章特别有用:

添加

where TKey : IEquatable<TKey>
其中TKey:IEquatable

应修复此问题并允许您使用Equals语法。

如果您使用f12键查看guid或int元数据,您将发现它实现了:

public struct int: IFormatable, IComparable, IComparable<int>, IEquatable<int> 
public struct Guid: IFormatable, IComparable, IComparable<Guid>, IEquatable<Guid>
公共结构int:IFormatable、IComparable、IComparable、IEquatable 公共结构Guid:IFormatable、IComparable、IComparable、IEquatable 那么约束条件将是:

public interface IRepository<TEntity, TKey> 
  where TEntity: class, IEntity<TKey>
  where TKey: struct, IFormatable, IComparable, IComparable<TKey>, IEquatable<TKey>
公共接口IRepository
其中tenty:类,tenty
其中TKey:struct,IFormatable,IComparable,IComparable,IEquatable
和IEntity接口必须如下所示:

public interface IEntity<TKey> where TKey: struct, IFormatable, 
                               IComparable, IComparable<TKey>, IEquatable<TKey>
公共接口属性,其中TKey:struct,IFormatable,
我可比,我可比,我可比

但是操作符==仍然不适用于我,但是Equals方法按照我们的预期工作,仍然在为equality操作符搜索解决方案。

每种可能的类型..我的意思是int、string等所有这些类型。在这种情况下,我会删除约束。int键不能满足约束。通过使用Equals解决了这个问题。谢谢!嗯没有。所以我删除了SelectByKey方法。。不幸的是。@Rushino为什么不等于功?它似乎应该是这样。@Rushino-它怎么不起作用-你得到了什么错误?是编译时错误还是运行时错误?@hatchet我得到了一个ru
public interface IRepository<TEntity, TKey> 
  where TEntity: class, IEntity<TKey>
  where TKey: struct, IFormatable, IComparable, IComparable<TKey>, IEquatable<TKey>
public interface IEntity<TKey> where TKey: struct, IFormatable, 
                               IComparable, IComparable<TKey>, IEquatable<TKey>