2011-11-04 35 views
1

这是我的表的简化SQL,它被转换为LINQ to 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) 
); 

现在我有这样的类(这些都是在不同的命名空间,从数据模型没有实体类)。

public class CampaignInfo { 
    public static CampaignModel Get(DataModel.CampaignInfo campaign) { 
     return new CampaignInfo { 
       Id = campaign.Id, 
       Name = campaign.Name, 
       Status = CampaignStatus.Get(c) 
     }; 
    } 
    public int Id {get; set;} 
    public int Name {get; set;} 
    public CampaignStatus { get; set;} 
} 

public class CampaignStatus { 
    public static CampaignStatus Get(DataModel.Campaign campaign) { 
     return new CampaignStatus { 
       Campaign = campaign.Id, // this is just for lookup on client side 
       ContractCount = campaign.Contracts.Count() 
       // There is much more fields concerning status of campaign 
     }; 
    } 
    public int Campaign { get; set; } 
    public int ContractCount {get; set;} 
} 

而且比我跑的查询:

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,因此不需要跟踪原始数据库实体。

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

现在我明白了,它不能神奇地创建表达式来使整个事情与一个查询。相反,它会分别计算每个广告系列的数量。在相当复杂的情况下,这是丑陋的放缓。

是否有一些简单的方法来实现这个目标?我想,这些类应该返回一些表达式,但我对这个领域完全陌生,我不知道该怎么做。在查询

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

+0

我想,我已经想出了一部分。现在使用pastebin,所以在这里不会太长。 http://pastebin.com/rttTgxyJ。而不是对象,我返回'Expression >'。但是我无法弄清楚如何用CampaignInfo打包CampaignStatus。 – FredyC

回答

3

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

LINQ(通过表达式树)的通用解决方案是创建一个筛选器或转换函数,该函数返回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() 
     }; 
} 

有了这个,你可以写下面的代码:

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 
     }; 
} 

有一个返回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 
     }; 

或添加额外的属性输出:

 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 
     }; 

这将转换到一个有效的SQL查询。查询不会从严格需要的数据库中获取更多记录或列。

+0

谢谢,但要么我不明白,或者它不是我正在寻找的。 'CampaignStatus'中肯定会有更多的字段,我想重复使用'Campaign'类。我已经更新了更多的例子。 – FredyC

+0

@FredyC:我更新了我的答案。我仍然认为这是你需要的。 – Steven

+0

我仍然缺少那里的一部分。您只将一个变量放到状态属性中,但我需要更多的变量。或者更具体一些。我需要整个Status对象并成为Campaign的一部分,或者可以独立运行。 – FredyC

0

您可以使用类似。

+0

这正是不想要的,因为可重用性:)在其他代码中,我想获取广告系列的状态。 'ContractStatus'中有更多的属性,这只是简短的版本。 – FredyC