2012-01-12 27 views
1

我有这个通用的存储库。为什么我不能使这个通用的知识库工作?什么不对?

/// <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); 
    } 

这里的具体实施...

public class ProductRepository : RepositoryBase<Product, int>, IProductRepository 
{ 
    public ProductRepository(IContext context) 
     : base(context) 
    { } 
/// <see cref="IProductRepository.cs"/> 
    public Product GetByName(string name) 
    { 
     return base.First(x => x.Name == name); 
    } 

    /// <see cref="IProductRepository.cs"/> 
    public IEnumerable<Product> FindProduct(Specification<Product> specification) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

当我创建特定的资源库..它说,TKEY必须是引用类型,但是为什么呢?有没有办法使这个通用的知识库工作?使用TKey是为了使方法SelectByKey接受键类型。

编辑#1:

如果我删除了约束的话,我有一个问题...... TKEY的不能使用== TKEY的在我的SelectByKey方法lambda表达式进行比较。

编辑#2:

尝试使用Equals和语法似乎是好。

编辑#3:

在运行时的Equals碰撞..说TKEY(这似乎是一个System.Object)不能使用,其似乎不逻辑由于对象具有相等的方法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> 
{ 
} 

,它似乎工作得很好。所以我会在今晚稍后尝试。

编辑#4

好吧例外我得到的是Canoot创造型的恒定值 “System.Object的”。此上下文仅支持主要类型,如int32,string和guid。

回答

2

在你的仓库声明

public abstract class RepositoryBase<TEntity, TKey> : IRepository<TEntity>, IDisposable 
    where TEntity : EntityBase<TKey> 
    where TKey : class 
{ 

您所指定的类约束,这将只允许引用类型。见

http://msdn.microsoft.com/en-us/library/d5x73970%28v=vs.80%29.aspx

其中T:类

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

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

除非您参与了学习练习,否则我不会尝试从头构建您的存储库。我会利用别人的做法。当我编写一个存储库框架时,我想要一个GetById方法,它可以处理不同类型的主键(尽管不是多个列主键)。当写它,我发现下面的两个职位特别有帮助:

C# LINQ to SQL: Refactoring this Generic GetByID method

http://goneale.com/2009/07/27/linq-to-sql-generic-repository/

+0

然后我得到一个错误,说TKey不能有操作== – Rushino 2012-01-12 00:37:46

+0

通过使用Equals来解决这个问题。谢谢! – Rushino 2012-01-12 01:08:54

+0

umm nope does not work。所以相反,我删除了SelectByKey方法..不幸的。 – Rushino 2012-01-12 02:08:58

0

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

你有约束:

where TKey : class

你需要的约束?你想支持哪些关键类型?

+0

每种可能的类型..我的意思是int,字符串等所有这些类型。 – Rushino 2012-01-12 00:31:45

+0

在这种情况下,我会删除约束。一个int键不会满足约束条件。 – David 2012-01-12 00:37:35

0

添加

where TKey : IEquatable<TKey> 

应该解决的问题,并允许您使用的Equals语法。

0

如果你看一看GUID或INT元数据使用F12键,你会本身,它实现:

public struct int: IFormatable, IComparable, IComparable<int>, IEquatable<int> 
public struct Guid: IFormatable, IComparable, IComparable<Guid>, IEquatable<Guid> 

那么约束将是:

public interface IRepository<TEntity, TKey> 
    where TEntity: class, IEntity<TKey> 
    where TKey: struct, IFormatable, IComparable, IComparable<TKey>, IEquatable<TKey> 

和IEntity接口必须是这样的:

public interface IEntity<TKey> where TKey: struct, IFormatable, 
           IComparable, IComparable<TKey>, IEquatable<TKey> 

但运算符==仍然没有为我工作,但Equals方法作为我们前工作仍在寻找平等运营商的解决方案。