2017-03-05 58 views
4

我有一個接受lambda表達式的方法,該表達式指定從表MyTable中選擇哪些列。如何使用LINQ返回C#中的所有屬性或其選擇?

public List<T> GetSelection<T>(string a, Expression<Func<MyTable, T>> columnsToSelect = null) 
{ 
    IQueryable<MyTable> query = _myTableRepository.Where(c => c.Name == a); 

    if (columnsToSelect != null) 
     return query.Select(columnsToSelect).ToList(); 

    return query.ToList(); // Intellisense gives an error here, please read on 
} 

正如你所看到的,columnsToSelectnull默認值,讓我把這種方法在任何有以下兩種方式:

// passing in a lambda expression to select the columns I want 
var result = GetSelection("AValue", t => new { t.Prop1, t.Prop2 }); 

// or like this, in which case I want all the columns 
var result = GetSelection("AValue"); 

我從智能感知得到的錯誤是這個:

無法隱式轉換 型 'System.Collections.Generic.List' 到 'System.Collections.Generic.List'

首先,我不明白這個令人困惑的錯誤消息,但我並沒有太多困擾它。也就是說,我認爲我需要的是一種將MyTable的整個對象轉換爲匿名類型然後返回它的列表的方法,並且通過整個對象我的意思是匿名類型對象將包含MyTable的所有屬性。我怎樣才能做到這一點?或者,如果還有其他更好的方法來實現我想要的,請提出建議。

+0

我覺得做這樣的工作的唯一辦法,將返回'object'。或者'動態'。 Lookie這裏http://stackoverflow.com/questions/10073319/returning-anonymous-type-in​​-c-sharp –

+0

@HristoYankov謝謝,但我非常反對使用動態,除非我真的必須。 –

回答

3

讓我把這種方法在任何有以下兩種:

...

var result = GetSelection("AValue"); 

不,這不會被允許。編譯器無法在這裏推斷出T的類型。唯一的解決方法是創建重載而不是使用默認值。在這一點問題變得微不足道解決:

public List<T> GetSelection<T>(
    string a, Expression<Func<MyTable, T>> columnsToSelect) 
{ 
    return _myTableRepository.Where(c => c.Name == a).Select(columnsToSelect) 
     .ToList(); 
} 

public List<MyTable> GetSelection<MyTable>(string a) 
{ 
    return GetSelection(a, t => t); 
} 
+0

我沒有看到我不能這樣稱呼它。對不起。所以在那種情況下,正如你已經說過的那樣,這個問題變得微不足道。我會堅持一個超載的版本methinks。或者只是按照你表達過少的表達方式來調用它。 –

1

我認爲你可以這樣做:

if (columnsToSelect != null) 
{ 
    var result = query.Select(s => s.GetType().GetProperty("columnName").GetValue(s, null).ToString()) 
         .Select(s => new MyTable() 
         { 
          YourProperty = s.ToString() 
         }).ToList(); 
} 
+0

但是我不使用反射和所有當我可以使用更簡單的方法,如[hvd](http://stackoverflow.com/a/42605942/3375713)所示。不管怎麼說,還是要謝謝你。 –

+0

加上它不能在LINQ to SQL中使用(儘管我還沒有嘗試過,但我很確定)。 –

1

如果你能定義一個接口爲您的桌面

public interface IMyTable<T> 
{ 
    string Name { get; set; } 
    T GetAll(); 
} 

那麼這將彙編

public List<T> GetSelection<T>(string a, Expression<Func<IMyTable<T>, T>> columnsToSelect = null) 
{ 
    IQueryable<IMyTable<T>> query = (IQueryable<IMyTable<T>>) _myTableRepository.Where(c => c.Name == a); 

    if (columnsToSelect == null) 
     columnsToSelect = (Expression<Func<IMyTable<T>, T>>)(table => (table.GetAll())); 

    return query.Select(columnsToSelect).ToList(); 

} 

的使用

一個演示
IMyTable<List<object>> xxx = new MyTable() { Surname = "b", Addresss = 1 }; 
xxx.Name = "a"; 
IMyTable<List<object>> yyy = new MyTable() { Surname = "d", Addresss = 2 }; 
yyy.Name = "c"; 
var repo = new List<IMyTable<List<object>>>() { xxx, yyy }.AsQueryable(); 
var Test = new Test<List<object>>(repo); 
var generic = Test.GetSelection<List<object>>("c"); 
var specific = Test.GetSelection<List<object>>("c", 
       (Expression<Func<IMyTable<List<object>>, List<object>>>) 
        (x => new List<object>() { x.Name, ((MyTable)x).Addresss })); 
var specifc2Columns = specific 
    .Select(rows => new { Name = rows[0], Address = rows[1] }); 

在演示表

internal class MyTable : IMyTable<List<object>> 
{ 
    public string Surname { get; set; } 
    public int Addresss { get; set; } 
    string IMyTable<List<object>>.Name{ get; set; } 
    List<object> IMyTable<List<object>>.GetAll() 
    { 
     return new List<object>() { ((IMyTable<List<object>>)this).Name, Surname, Addresss }; 
    } 
} 
+0

感謝您所展示的所有內容。但我認爲你也會同意,[hvd](http://stackoverflow.com/a/42605942/3375713)顯示的是一種更簡單的方法。 –

+0

我認爲這不會起作用。 'Expression <...>'的使用表明查詢提供者正在被使用,而不是使用'EnumerableQuery'(否則,簡單的'Func <...>'會更好)。查詢提供者通常不喜歡對自定義方法的調用。除此之外,如果以行爲單位而不是以列爲單位返回每個「MyTable」實例的屬性值將會令我感到意外,並且它非常脆弱,因爲'(Expression ,T >>)'將在運行時失敗除非'T'完全是'List ',這對調用者來說是不清楚的。 – hvd

+0

@hvd你想讓我展示一個可行的例子嗎?讓我在一分鐘內更新答案 – 2017-03-05 09:11:00

相關問題