2013-04-05 92 views
3

所以我想为一个where查询制作一个通用函数,而不是使用版本库 所以有可能做这样的事情?Generic DBContext for Where Query

public IEnumerable<T> Something<T>(int authorId) where T : class 
    { 
     return Vmsb.Set<T>().Where(c => c.AuthorId== authorId); 

    } 

现在我不能,因为它不知道c.AuthorId是什么

+0

你为什么不试试看看是否有可能? – Artless 2013-04-05 22:07:38

+0

我尝试,我不能这样Iam问,有可能以其他方式做到这一点,在通用不知道如何知道在哪里条款 – 2013-04-05 22:08:30

+0

的财产那么,想想这样。 BookContext有一个'Book'类型的表,而PeopleContext有一个'Person'类型的表。有了这样一个函数,你可以让BookContext给你一个'Person'对象,这会导致一个异常。你想通过这种抽象来实现什么? – Artless 2013-04-05 22:11:21

回答

3

创建一个接口IHaveAuthor并与该属性指定它在局部类:

public interface IHaveAuthor 
{ 
    int AuthorId { get; set; } 
} 

//Note that the interface is already implemented in auto-generated part. 
//Or if it's Code First, just specify it directly on your classes. 
public partial class Book : IHaveAuthor 
{ 
} 

public partial class Article : IHaveAuthor 
{ 
} 

再点界面在通用类型where约束下:

public IEnumerable<T> GetAuthorPublicationsOf<T>(int authorId) 
    where T : class, IHaveAuthor 
{ 
    return Vmsb.Set<T>().Where(c => c.AuthorId == authorId); 
} 

和使用:

var authorBooks = query.GetAuthorPublicationsOf<Book>(authorId); 
var authorArticles = query.GetAuthorPublicationsOf<Article>(authorId); 
+1

我在我自己的代码中使用了EF Code First的这种策略 - 这是有效的。 – 2013-04-05 23:24:01

2

添加到Olexander's answer,因为EF建议您使用工作单元模式,我通常不会在我的方法假定的DbContext - 我通过在最通用的对象可能不是。同样也是风格问题,我喜欢返回界面。

编辑更新为包括Olexander使用IQueryable而不是IEnumerable的重要修复。

所以我的方法签名看起来像:

public IQueryable<IHaveAuthor> Something(int authorId, IQueryable<IHaveAuthor> items) 
{ 
    return items.Where(c => c.AuthorId == authorId); 
} 

所以调用,这将是比你当前呼叫有点不同 - 大概是这样的:

var db = new MyDbContext(); 
var items = db.Books; 
var itemForAuthor1 = Something(1, items); 

否则你的“东西”方法不是非常灵活 - 它假定您当前对象上存在单个现有的DbContext,这可能不是一个安全的假设(因为它只应该在这个小块的工作中生存,无论它是什么),您不能连锁它与其他命令等

+0

克里斯,谢谢你引用我;)我已经更新了我的答案,似乎更漂亮。你现在可以修复404链接吗?谢谢! – Olexander 2013-04-05 23:58:35

+0

我会考虑通过'IQueryable '而不是'IEnumerable '。在您的代码示例中,它将枚举Web服务器内存中的所有实体,而不是执行SQL查询。所以如果你在db表中有数百行,你肯定会遇到明显的性能问题。 – Olexander 2013-04-06 00:57:08

+0

@Olexander修复链接。然而你所做的IEnumerable断言是不正确的;我上面的代码不会导致项目在内存中枚举 - 查询将等待直到您采取后续操作(如调用.ToArray())。尝试一下。 – 2013-04-07 19:26:57

0

迭戈希望我的代码可以帮助你。

protected List<T> ListAll<T>() where T : class 
    { 
     using (MyDbContext db = new MyDbContext()) 
     { 
      return db.Set(typeof(T)).Cast<T>().AsNoTracking<T>().ToList(); 
     } 

    } 


    protected T ListAllById<T>(int id) where T : class 
    { 
     using (MyDbContext db = new MyDbContext()) 
     { 
      return db.Set(typeof(T)).Cast<T>().Find(id); 
     } 
    } 

    protected void InsertObj(Object obj) 
    { 
     using (MyDbContext db = new MyDbContext()) 
     { 
      db.Set(obj.GetType()).Add(obj); 
      db.SaveChanges(); 
     } 
    } 

    protected void UpdateObj(Object obj) 
    {  
     try 
     { 
      using (MyDbContext db = new MyDbContext()) 
      { 
       db.Set(obj.GetType()).Attach(obj); 
       db.Entry(obj).State = EntityState.Modified; 
       db.SaveChanges(); 
      } 
     } 
     catch (System.Exception ex) 
     { 
      System.Windows.Forms.MessageBox.Show(" " + ex.Message); 
     }    
    } 

    protected void DeleteObj(Object obj) 
    { 
     using (MyDbContext db = new MyDbContext()) 
     { 
      db.Set(obj.GetType()).Attach(obj); 
      db.Entry(obj).State = EntityState.Deleted; 
      db.SaveChanges(); 
     } 

    } 
+0

请添加关于什么的简要说明代码不是只发布代码。 – Joel 2013-10-17 13:24:19