2017-03-14 54 views
0

比方说,我有一个实体Container有四个特性:ContainerID(整数),ContainerNumber(字符串),Title(字符串),并Date(日期)。显示在LINQ自定义字段到实体动态选择

我有第二个实体,称为ContainerCustomFields具有三个属性:CustomFieldID(整数),ContainerID(整数和外键),FieldName(字符串),FieldContent(字符串)。 ContainerCustomFields实体存储用户定义的Container实体的自定义字段。数据是这样的:

集装箱:

Container 
--------- 
ID |  Number  |  Title  | Date  | 
===================================================== 
1 |  10000  | 1st Title | 1/12/2017 | 
2 |  10543  | 2nd Title | 1/31/2017 | 
3 |  10667  | 3rd Title | 4/12/2016 | 
4 |  12889  | 4th Title | 5/23/2012 | 

自定义字段:

ID | ContainerID | FieldName | Content | 
===================================================== 
1 |  1  | Colour  | Blue  | 
2 |  1  | Height  | 5000  | 
3 |  1  | Length  | 9100  | 
4 |  4  | Colour  | Gray  | 

是否有可能返回数据,所以它看起来是这样的:

Container 
--------- 
ID |  Number  |  Title  | Date  | Colour | Height | Length | 
==================================================================================== 
1 |  10000  | 1st Title | 1/12/2017 | Blue | 5000 | 9100 | 
2 |  10543  | 2nd Title | 1/31/2017 |   |   |   | 
3 |  10667  | 3rd Title | 4/12/2016 |   |   |   | 
4 |  12889  | 4th Title | 5/23/2012 | Gray |   |   | 

我能够获得每个容器的自定义字段及其值的列表以及选择我想要的列从实体使用select语句。我如何结合这两个陈述?

For Each customField In _db.ContainerCustomFields 
    .Where(Function(cf) cf.ContainerID = newBox.ContainerID) 

returnContainers.Select(Function(c) New With 
    {.ContainerID = c.ContainerID, 
    .Number = c.ContainerNumber, 
    .Title = c.Title, 
    .Date = c.Date }) 

我正在使用Web API 2将它作为匿名类型返回给我的Web应用程序。

+0

为什么一定要用匿名类型? –

+0

@DavidG我很好,无论是C#或VB。更多的人熟悉C#。 – Nse

+0

@LeiYang我正在使用Web API 2将我的结果返回到Kendo UI网格。需要对数据进行一些处理,而不是所有的字段都是必需的。 – Nse

回答

0

第一组到每个容器,把字段&值到阵列中的GRPS内:

var grps = from c in _db.Containers 
join ccf in _db.ContainerCustomFields 
    on c.ContainerID equals ccf.ContainerID 
select new 
     {ContainerId = c.ContainerID, 
     ContainerNumber= c.ContainerNumber, 
     Title = c.Title, 
     Date = c.Date, 
     FieldName = ccf.FieldName, 
     FieldContent = ccf.FieldContent} 
into f 
group f by f.ContainerId 
into myGroup 
select new 
{ 
    ContainerId = myGroup.Key, 
    ContainerNumber = myGroup.Max(d => d.ContainerNumber), 
    Title = myGroup.Max(d => d.Title), 
    Date = myGroup.Max(d => d.Date), 
    Fields = myGroup.Select(d => d.FieldName).ToArray(), 
    Values = myGroup.Select(d => d.FieldContent).ToArray() 
}; 

现在找到的所有字段名称可以出现:

var fields = from ccf in _db.ContainerCustomFields 
      group ccf by ccf.FieldName 
      into grp 
      select grp.Key; 

现在创建一个数据表是包含我们的容器和所有可能的字段列:

DataTable dt = new DataTable(); 
dt.Columns.Add("ContainerId", typeof(Int32)); 
dt.Columns.Add("ContainerNumber", typeof(String)); 
dt.Columns.Add("Title", typeof(String)); 
dt.Columns.Add("Date", typeof(DateTime)); 
foreach(var fld in fields) 
{ 
    dt.Columns.Add(fld, typeof(String)); 
} 

现在每个组数据的添加一行到我们的DataTable,并为相关的每个字段添加值:

foreach (var row in grps) 
{ 
    DataRow dr = dt.NewRow(); 
    dr["ContainerId"] = row.ContainerId; 
    dr["ContainerNumber"] = row.ContainerNumber; 
    dr["Title"] = row.Title; 
    dr["Date"] = row.Date; 
    for (int i = 0; i < row.Fields.Count(); i++) 
    { 
     dr[row.Fields[i]] = row.Values[i]; 
    } 
    dt.Rows.Add(dr);  
} 

现在你可以使用数据表填写网格或什么的。数据表中缺少的字段值将被设置为空。

设置代码,我使用的数据库表:

CREATE TABLE Container 
(
    ContainerID Int, 
    ContainerNumber Varchar(50), 
    Title Varchar(50), 
    [Date] Date 
) 

INSERT INTO Container 
VALUES 
(1, '10000', '1st Title', '2017-01-12'), 
(2, '10543', '2nd Title', '2017-01-31'), 
(3, '10667', '3rd Title', '2017-04-12'), 
(4, '12889', '4th Title', '2017-05-23') 


CREATE TABLE ContainerCustomFields 
(
    CustomFieldID INT, 
    ContainerID Int, 
    FieldName Varchar(50), 
    FieldContent Varchar(50) 
) 

INSERT INTO ContainerCustomFields 
VALUES 
(1,1, 'Colour', 'Blue'), 
(2,1, 'Height', '5000'), 
(3,1, 'length', '9100'), 
(4,4, 'Colour', 'Gray')