C# 使用泛型方法返回列表<;T>;其中T可以是共享相同结构的三种类型之一

C# 使用泛型方法返回列表<;T>;其中T可以是共享相同结构的三种类型之一,c#,linq-to-sql,C#,Linq To Sql,我有一些使用不同源表的sql视图,但每个视图返回完全相同的结构 非常简单地说: view1 select tblA.Name as custName, tblA.DOB as DateOfBirth, tblA.accountBalance as AccountBalance from myFirstTable tblA view2 select tblB.AccountName as custName,

我有一些使用不同源表的sql视图,但每个视图返回完全相同的结构

非常简单地说:

view1
    select tblA.Name as custName,
           tblA.DOB as DateOfBirth,
           tblA.accountBalance as AccountBalance
    from myFirstTable tblA

view2
    select tblB.AccountName as custName,
           tblB.BirthDate as DateOfBirth,
           tblB.Balance as AccountBalance
    from mySecondTable tblB

view3
    select tblC.CustomerName as custName,
           tblC.DateOfBirth as DateOfBirth,
           tblC.accBal as AccountBalance
    from myThirdTable tblC
因此,尽管源表中的字段名不同,但不同的视图返回相同名称(和类型)的字段。实际的视图是复杂而庞大的,每个视图都有数百行

然后,我将这些视图拖到我的LINQtoSQL设计器中,并尝试在泛型类中使用它们

    public static List<T> MainSearch<T>(ReportParams RP)
    {
        MyDataContext dc = new MyDataContext();

        if (string.IsNullOrEmpty(RP.appType)) { return null; }

        var searchQuery = new List<T>();

        switch (RP.appType)
        {
            case "type1":
                searchQuery = (from t in dc.view1s select t);
                break;
            case "type2":
                searchQuery = (from t in dc.view2s select t);
                break;
            case "type3":
                searchQuery = (from t in dc.view3s select t);
                break;
        }

        //do other stuff with search query depending on params
        DateTime dtFrom = Convert.ToDateTime(RP.fromDate);
        searchQuery = searchQuery.Where(q => convert.ToDateTime(q.DateOfBirth) >= dtFrom);

        //and so on...
publicstaticlistmainsearch(ReportParams RP)
{
MyDataContext dc=新的MyDataContext();
if(string.IsNullOrEmpty(RP.appType)){return null;}
var searchQuery=新列表();
开关(RP.appType)
{
案例“类型1”:
searchQuery=(从dc.view1s中的t选择t);
打破
案例“类型2”:
searchQuery=(从dc.view2s中的t选择t);
打破
案例“类型3”:
searchQuery=(从dc.view3s中的t选择t);
打破
}
//根据参数对搜索查询执行其他操作
DateTime dtFrom=转换为日期时间(RP.fromDate);
searchQuery=searchQuery.Where(q=>convert.ToDateTime(q.DateOfBirth)>=dtFrom);
//等等。。。
其思想是,可以使用通用前端,根据用户选择传入参数,然后使用这些参数缩小搜索特定源数据的搜索结果范围(它永远不会返回组合,始终是三个视图中的一个或另一个)

上面的代码不起作用。在我的switch语句中,intellisense抱怨它无法将特定类型(例如view1)隐式转换为T的泛型列表。这就阻止了我在后面的lambda表达式中使用强类型


在实体框架中,正确的方法是创建一个独立的
TBase
类,该类是
T1
T2
T3
派生的。它将包含您需要的所有公共属性,因此re不需要使用
开关
语句:您只需要
TBase-someObj;
,然后就可以直接使用
someObj.ACommonProperty

如果您有一个类具有与视图返回的属性相同的属性集,那么您可以尝试以下方法:

case "type1":
searchquery = (from t in dc.view1s select new commonClass() { CustName = t.CustName, DateOfBirth = t.DateOfBirth, AccountBalance = t.AccountBalance });
                break;

等等,在其他情况下…

我还没有完全测试过这一点,但我认为您可以通过创建一个带有属性custName、DOB和AccountBalance的接口来实现。然后创建每个生成的LINQ to SQL类(tblA、tblB、tblC)在一个单独的部分类文件中实现这个接口。只要属性名和类型匹配,就可以了

interface IAccountTable
{
    string custName { get; set; }
    DateTime DOB { get; set; }
    Decimal AccountBalance { get; set; }
}

使您的searchQuery成为该界面的列表

var searchQuery = new List<IAccountTable>();
searchQuery = tblA.Where(t => t.custName == "Uday").Select(t => (IAccountTable)t).ToList();

我不认为LINQ to SQL支持继承。但是,当我不使用实体框架时,这没有多大帮助!我说我使用的是LINQ to SQL。这很好也很简单:)它是,而且可能是唯一的前进方向。这只是意味着,由于每个视图都有大约60个字段,我将从三个不同的视图中得到3组60个手动映射到公共类。我可以复制/粘贴它,只需更改视图名称,但这似乎非常不公平!我以前没有使用过AutoMapper,但为了避免使用手动映射,这可能是值得研究的问题。入门:关于使用AutoMapper映射对象列表,这里有一个非常重要的问题:Linq到SQL不支持这是一种继承,不是吗?每次我接触设计器时,我都会覆盖我所做的任何自定义更改。由于视图返回大约60个字段,单独维护这些字段会有点令人沮丧,但我开始认为,无论我采取哪种方法,我都将不得不做类似的事情。不,你不要接触设计gner.LINQ to SQL创建分部类。因此,您可以在另一个文件夹中创建补充分部类。这些对于实现接口(如上所述)或添加自定义属性和方法非常有用。好的……但是“…designer.cs”中的分部类文件必须映射到数据库上的视图源,以便查询知道从何处获取它。因此我有:`[global::System.Data.Linq.Mapping.TableAttribute(Name=“dbo.view1”)``并在该
公共部分类view1
下,然后是属性列表(在designer.cs文件中)。你是说我需要更改它,以便只继承接口并保留映射吗?不。为每个具有相同类名的视图创建单独的分部类文件。将这些文件保存在单独的文件夹中,并将其命名为tblA.partial.cs(或其他名称)。在这些新的部分类文件中,指定该类实现接口。编译器将知道如何将单独的部分文件合并到单个类中。也许这个问题和答案会让问题更清楚。
searchQuery = tblA.Where(t => t.custName == "Uday").Select(t => (IAccountTable)t).ToList();