2011-05-24 64 views
1

我正在一個MVC3項目中工作,並且我正在使用LINQ to SQL。我有一個數據庫模式,使用一個字段來指示記錄是活動還是刪除(字段是布爾名爲「活動」)。 現在假設有兩個鏈接的表,如State和City,其中City引用狀態。 比方說,我有一個返回狀態的列表的方法:有沒有在LINQ DataContext中實現選擇條件的方法

public ActionResult ListStates() 
{ 
    return View(_repository.ListStates()); 
} 

現在,我已經實現了庫方法返回的所有狀態,我可以通過以下方式實現:

public class Repository 
{ 
    public IQueryable<State> ListStates() 
    { 
     return dataContext.States.Where(p => p.Active == true) 
    } 
} 

在視圖中,我可以確定我只使用活動狀態。但爲了確保我只使用活躍的城市,我需要在視圖中對其進行過濾,這使得視圖更加醜陋,或者實現了自定義視圖模型。這兩種情況都是有效的,但他們需要很多工作。 我看到有數據方面的方法,其中一個對象被插入之前,我們就可以實現一定的操作/更新到數據庫,因爲這examle:

public partial class DatabaseDataContext 
{ 
    partial void InsertState(State instance) 
    { 
     instance.Active = true; 
     this.ExecuteDynamicInsert(instance); 
    } 
} 

每當狀態對象的插入是上述方法被執行發生。 我的問題是,是否有一種方法只能在一個地方爲一個對象實現一個條件,例如只有在執行選擇時才返回活動記錄?

+0

記得按Ctrl + K的關鍵是:d – TheVillageIdiot 2011-05-24 15:05:45

回答

1

如果我理解正確,那麼您正試圖消除在您的存儲庫的方法中指定.Where(p => p.Active == true)的需要,並且您只想定義它一次。

我不確定是否可以在不創建數據上下文包裝的情況下實現此目的,因爲對於每個查詢,您必須將兩個邏輯表達式組合起來,該表達式來自存儲庫和p => p.Active == true

最簡單的解決辦法如下:

/// <summary> 
/// A generic class that provides CRUD operations againts a certain database 
/// </summary> 
/// <typeparam name="Context">The Database context</typeparam> 
/// <typeparam name="T">The table object</typeparam> 
public class DataContextWrapper<Context> where Context : DataContext, new() 
{ 
    Context DataContext; 


    /// <summary> 
    /// The name of the connection string variable in web.config 
    /// </summary> 
    string ConnectionString 
    { 
     get 
     { 
      return "Connection String"; 
     } 
    } 

    /// <summary> 
    /// Class constructor that instantiates a new DataContext object and associates the connection string 
    /// </summary> 
    public DataContextWrapper() 
    { 
     DataContext = new Context(); 
     DataContext.Connection.ConnectionString = ConnectionString; 
    } 


    protected IEnumerable<T> GetItems<T>([Optional] Expression<Func<T, bool>> query) where T : class, new() 
    { 
     //get the entity type 
     Type entity = typeof(T); 
     //get all properties 
     PropertyInfo[] properties = entity.GetProperties(); 

     Expression<Func<T, bool>> isRowActive = null; 
     //we are interested in entities that have Active property ==> to distinguish active rows 
     PropertyInfo property = entity.GetProperties().Where(prop => prop.Name == "Active").SingleOrDefault(); 

     //if the entity has the property 
     if (property != null) 
     { 
      //Create a ParameterExpression from 
      //if the query is specified then we need to use a single ParameterExpression for the whole final expression 
      ParameterExpression para = (query == null) ? Expression.Parameter(entity, property.Name) : query.Parameters[0]; 

      var len = Expression.PropertyOrField(para, property.Name); 
      var body = Expression.Equal(len, Expression.Constant(true)); 
      isRowActive = Expression.Lambda<Func<T, bool>>(body, para); 
     } 

     if (query != null) 
     { 
      //combine two expressions 
      var combined = Expression.AndAlso(isRowActive.Body, query.Body); 
      var lambda = Expression.Lambda<Func<T, bool>>(combined, query.Parameters[0]); 
      return DataContext.GetTable<T>().Where(lambda); 
     } 
     else if (isRowActive != null) 
     { 
      return DataContext.GetTable<T>().Where(isRowActive); 
     } 
     else 
     { 
      return DataContext.GetTable<T>(); 
     } 

    } 

} 

然後你就可以像這樣創建庫:

/// <summary> 
/// States Repository 
/// </summary> 
public class StatesRepository : DataContextWrapper<DEMODataContext> 
{ 
    /// <summary> 
    /// Get all active states 
    /// </summary> 
    /// <returns>All active states</returns> 
    public IEnumerable<State> GetStates() 
    { 
     return base.GetItems<State>(); 
    } 

    /// <summary> 
    /// Get all active states 
    /// </summary> 
    /// <param name="pattern">State pattern</param> 
    /// <returns>All active states tha contain the given pattern</returns> 
    public IEnumerable<State> GetStates(string pattern) 
    { 
     return base.GetItems<State>(s=>s.Description.Contains(pattern)); 
    } 

} 

用法:

StatesRepository repo = new StatesRepository(); 
var activeStates = repo.GetStates(); 

var filtered = repo.GetStates("Al"); 

希望這有助於;)

+0

雖然你的解決方案很好,但它仍然不是我要找的。 – Mentor 2011-05-26 07:48:22