2012-05-11 41 views
1

我在用C#建一個文件下載服務的過程是 - 該過程的一部分,從一個或多個數據庫驗證下載,並提供下載的細節。C# - 選擇實體和可變LINQ /查詢

有四個數據庫驗證過程可以稱之爲 - 這真的取決於其服務的下載適用。數據庫可以是MSSQL或MySQL,可以使用存儲過程(複雜類型)或帶有多個連接的LINQ查詢。所有結果將包含相同的列信息。

我已經定義了實體框架內的數據庫,我很高興在單一實例的代碼 - 如果我查詢不同的數據庫,我不希望再次寫代碼,做同樣的工作。

我已經搜索了幾個小時試圖找到一個解決方案,使我能夠指定實體和查詢使用根據條件,並保持它的強類型。

存儲過程的查詢我使用這樣的代碼:

using (myEntity1 ctx = new myEntity1()) 
{ 
    var results = ctx.MyStoredProcedure(param1, param2); 

    foreach (var result in results) 
    { 
     // do stuff here 
    } 
} 

因爲我可以用這樣的代碼LINQ查詢:

using (myEntity2 ctx = new myEntity2()) 
{ 
    var results = (from t in ctx.table select new { t.Col1, t.Col2,}); 

    foreach (var result in results) 
    { 
     // do stuff here 
    } 
} 

概括地說,我希望能夠根據許多條件指定實體和查詢。我也希望結果是強類型的。這似乎很簡單,但我找不到有效的答案。

感謝

克里斯

+0

[這](http://stackoverflow.com/questions/9762 808/change-fluent-api-mapping-dynamic)看起來有點像你想要的。 –

回答

0

後不停學習的一年,如果我這樣做,現在我可能會使用一個存儲庫,以每個數據集加載到其POCO則項目中的這些波蘇斯成一個其實我想,可能使用該擴展方法:

public static class QueryableExtensions 
{ 

    public static ProjectionExpression<TSource> Project<TSource>(this IQueryable<TSource> source) 
    { 
     return new ProjectionExpression<TSource>(source); 
    } 

    public static string GetSQL<TSource>(this IQueryable<TSource> source) 
    { 
     return source.ToString(); 
    } 
} 

public class ProjectionExpression<TSource> 
{ 
    private static readonly Dictionary<string, Expression> ExpressionCache = new Dictionary<string, Expression>(); 

    private readonly IQueryable<TSource> _source; 

    public ProjectionExpression(IQueryable<TSource> source) 
    { 
     _source = source; 
    } 

    public IQueryable<TDest> To<TDest>() 
    { 
     var queryExpression = GetCachedExpression<TDest>() ?? BuildExpression<TDest>(); 

     return _source.Select(queryExpression); 
    } 

    private static Expression<Func<TSource, TDest>> GetCachedExpression<TDest>() 
    { 
     var key = GetCacheKey<TDest>(); 

     return ExpressionCache.ContainsKey(key) ? ExpressionCache[key] as Expression<Func<TSource, TDest>> : null; 
    } 

    private static Expression<Func<TSource, TDest>> BuildExpression<TDest>() 
    { 
     var sourceProperties = typeof(TSource).GetProperties(); 
     var destinationProperties = typeof(TDest).GetProperties().Where(dest => dest.CanWrite); 
     var parameterExpression = Expression.Parameter(typeof(TSource), "src"); 


     var bindings = destinationProperties 
          .Select(destinationProperty => BuildBinding(parameterExpression, destinationProperty, sourceProperties)) 
          .Where(binding => binding != null); 

     var expression = Expression.Lambda<Func<TSource, TDest>>(Expression.MemberInit(Expression.New(typeof(TDest)), bindings), parameterExpression); 

     var key = GetCacheKey<TDest>(); 

     ExpressionCache.Add(key, expression); 

     return expression; 
    } 

    private static MemberAssignment BuildBinding(Expression parameterExpression, MemberInfo destinationProperty, IEnumerable<PropertyInfo> sourceProperties) 
    { 
     var sourceProperty = sourceProperties.FirstOrDefault(src => src.Name == destinationProperty.Name); 

     if (sourceProperty != null) 
     { 
      return Expression.Bind(destinationProperty, Expression.Property(parameterExpression, sourceProperty)); 
     } 

     var propertyNames = SplitCamelCase(destinationProperty.Name); 

     if (propertyNames.Length == 2) 
     { 
      sourceProperty = sourceProperties.FirstOrDefault(src => src.Name == propertyNames[0]); 

      if (sourceProperty != null) 
      { 
       var sourceChildProperty = sourceProperty.PropertyType.GetProperties().FirstOrDefault(src => src.Name == propertyNames[1]); 

       if (sourceChildProperty != null) 
       { 
        return Expression.Bind(destinationProperty, Expression.Property(Expression.Property(parameterExpression, sourceProperty), sourceChildProperty)); 
       } 
      } 
     } 

     return null; 
    } 

    private static string GetCacheKey<TDest>() 
    { 
     return string.Concat(typeof(TSource).FullName, typeof(TDest).FullName); 
    } 

    private static string[] SplitCamelCase(string input) 
    { 
     return Regex.Replace(input, "([A-Z])", " $1", RegexOptions.Compiled).Trim().Split(' '); 
    } 
} 

http://www.devtrends.co.uk/blog/stop-using-automapper-in-your-data-access-code