2013-04-05 96 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