C# LINQ到SQL数据结构的分离和重用

C# LINQ到SQL数据结构的分离和重用,c#,linq,linq-to-sql,c#-4.0,reusability,C#,Linq,Linq To Sql,C# 4.0,Reusability,下面是我的表的简化SQL,它被转换为LINQ to SQL模型 CREATE TABLE Campaign ( Id int PRIMARY KEY, Name varchar NOT NULL ); CREATE TABLE Contract ( Id int PRIMARY KEY, CampaignId int NULL REFERENCES Campaign(Id) ); 现在我有了这样的类(它们在不同的名称空间中,而不是datamodel中的实体类)

下面是我的表的简化SQL,它被转换为LINQ to SQL模型

CREATE TABLE Campaign (
    Id int PRIMARY KEY,
    Name varchar NOT NULL
);
CREATE TABLE Contract (
    Id int PRIMARY KEY,
    CampaignId int NULL REFERENCES Campaign(Id)
);
现在我有了这样的类(它们在不同的名称空间中,而不是datamodel中的实体类)

然后我运行查询:

dataContext.Campaigns.Select( c => CampaignInfo.Get( c ) );
其他代码可以执行以下操作:

dataContext.Campaigns.Where( c => c.Name == "DoIt" ).Select( c => CampaignInfo.Get( c ) );
或者我想获取活动的状态列表:

dataContext.Campaigns.Select( c => CampaignStatus.Get( c ) );
注意:这些调用的结果被转换为JSON,因此不需要跟踪原始db实体

正如你所看到的,有两个目标。控制从数据库中获取的数据,并在其他地方重用这些结构。然而,这种方法是一个巨大的错误,因为类返回对象并在表达式树中使用它

现在我明白了,它不能神奇地创建一个表达式,用一个查询就完成整个过程。相反,它在每一次竞选活动中都是独立的。在相当复杂的情况下,这是丑陋的减速


有什么简单的方法可以做到这一点吗?我想,这些类应该返回一些表达式,但我对这个领域完全不熟悉,不知道该怎么办。

您可以使用以下内容:

using( var dataContext = new DataModel.ModelDataContext() )  
{  
    dataContext.Campaigns.Select( c => new {  
            Id = c.Id,  
            Name = c.Name,  
            Status = new CampaignStatus()  
            {  
                ContractCount = c.Contracts.Count()  
            }  
        })  
}

在您的查询中。

如果我理解正确的话,一般的问题是您有一些业务逻辑,您不希望在整个代码中重复这些逻辑(DRY)。您希望能够在LINQ方法中使用此逻辑

LINQ(over Expression trees)的一般解决方案是创建一个过滤器或转换函数,该函数返回一个
IQueryable
,以便在将该查询发送到数据库之前对其进行进一步处理

以下是一种方法:

// Reusable method that returns a query of CampaignStatus objects
public static IQueryable<CampaignStatus> 
    GetCampaignStatusses(this IQueryable<Compaign> campaigns)
{
    return
        from campaign in campaigns
        new CampaignStatus
        {
            Campaign = campaign.Id,
            ContractCount = compaign.Contracts.Count()
        };
}
拥有一个返回
IQueryable
的方法,可以让您执行各种额外的操作,而该方法并不知道。例如,您可以添加过滤:

        from campaign in db.Campaigns.WithContractCount()
        from status in db.Campaigns.GetCampaignStatusses()
        where campaign.Id == status.Campaign
        where campaign .Name == "DoIt"
        where status .ContractsCount < 10
        select new
        {
            Id = campaign.Id,
            Name = campaign.Name,
            Status = status
        };

这将转换为高效的SQL查询。查询从数据库中获取的记录或列不会超过严格需要的数量。

这正是我不希望看到的,因为可重用性:)在其他一些代码中,我只想获取活动的状态。
ContractStatus
中有更多属性,这只是一个简短的版本。谢谢,但要么我不明白,要么这不是我要找的。在
CampaignStatus
中肯定会有更多的字段,我也想重用
Campaign
类。我更新了问题,增加了例子。@FredyC:我更新了答案。我仍然认为这是你需要的。我仍然缺少一部分。您只在Status属性中添加了一个变量,但我需要更多的变量。或者更具体地说。我需要那个状态对象作为一个整体,作为活动的一部分,或者能够独立。@FredyC:在我的示例中,我初始化了2个属性。如果你愿意,你可以加更多。诀窍是在LINQ(IQueryable)查询中进行初始化,并在整个应用程序中重用该查询。这是能够在其他LINQ查询中重用该逻辑的方法。抱歉,但我仍然没有看到它。当我说“给我
状态
”时,它需要有固定的
状态结构
。当我说“给我
活动
”时,它需要有
活动
信息,其中的
状态
结构完全相同。我不需要是可配置的。这些都是MVC的模型,它需要始终具有相同的结构…类似这样的东西:我想,我已经找到了其中的一部分。现在正在使用pastebin,所以不会太久。我返回的不是object,而是
表达式
。但是,我不知道如何用活动信息包装活动状态。
using (var db = new DataModel.ModelDataContext() ) 
{
    return
        from campaign in db.Campaigns.WithContractCount()
        from status in db.Campaigns.GetCampaignStatusses()
        where campaign.Id == status.Campaign
        select new
        {
            Id = campaign.Id,
            Name = campaign.Name,
            Status = status
        };
}
        from campaign in db.Campaigns.WithContractCount()
        from status in db.Campaigns.GetCampaignStatusses()
        where campaign.Id == status.Campaign
        where campaign .Name == "DoIt"
        where status .ContractsCount < 10
        select new
        {
            Id = campaign.Id,
            Name = campaign.Name,
            Status = status
        };
        from campaign in db.Campaigns.WithContractCount()
        from status in db.Campaigns.GetCampaignStatusses()
        where campaign.Id == status.Campaign
        select new
        {
            OtherProp = campaign.OtherProp,
            Id = status.Campaign,

            Name = campaign.Name,
            Status = status
        };