Привет, я довольно новичок в API-интерфейсе Entity и Linq.
И у меня возникли проблемы с тем, что я мог бы легко сделать в SQL и веб-формах.
Сначала я использовал базу данных EF (для базы данных, которую я не создал и не могу изменить)
Чтобы вернуть 3 таблицы, первые две таблицы:
Список моделей (fc_models) с полем, содержащим int (ModelSeq), который является первичным ключом
Список деталей (fc_linkedParts), связанных с моделями в первой таблице. для него установлено то же поле (ModelSeq), что и для внешнего ключа, а ModelSeq и Partnum - для первичного ключа.
Третья таблица представляет собой список классов Part, она содержит поле ClassId и поле Description. Что касается базы данных, то нет связи между этой таблицей и частями FC_linked, но, конечно, в SQL я могу просто присоединиться к ClassId как в этой таблице, так и в таблице fc_linkedparts
У меня есть свои модели данных, созданные структурой сущностей.
namespace DBF_Models
{
using System;
using System.Collections.Generic;
public partial class fc_Models
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public fc_Models()
{
this.fc_LinkParts = new HashSet<fc_LinkParts>();
}
public int ModelSeq { get; set; }
public string ModelId { get; set; }
public string ModelDesc { get; set; }
public string Manufacturer { get; set; }
public string Category { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<fc_LinkParts> fc_LinkParts { get; set; }
}
}
namespace DBF_Models
{
using System;
using System.Collections.Generic;
public partial class fc_LinkParts
{
public int ModelSeq { get; set; }
public string PartNum { get; set; }
public string PartDescription { get; set; }
public string Manufacturer { get; set; }
public string PartClass { get; set; }
public virtual fc_Models fc_Models { get; set; }
}
}
namespace DBF_Models
{
using System;
using System.Collections.Generic;
public partial class PartClass
{
public string Company { get; set; }
public string ClassID { get; set; }
public string Description { get; set; }
public string BuyerID { get; set; }
public bool RcvInspectionReq { get; set; }
public string CommodityCode { get; set; }
public bool AvailForReq { get; set; }
public decimal MtlBurRate { get; set; }
public bool SplitPOLine { get; set; }
public string NegQtyAction { get; set; }
public string PurchCode { get; set; }
public bool ConsolidatedPurchasing { get; set; }
public bool GlobalPartClass { get; set; }
public bool GlobalLock { get; set; }
public byte[] SysRevID { get; set; }
public System.Guid SysRowID { get; set; }
}
}
Мне не нужна вся информация в таблицах, поэтому я создал несколько DTO (плюс я следовал решению с такой же проблемой, что и у меня в то время)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DBF_Models.Models
{
public class ModelDto
{
public int ModelSeq { get; set; }
public string ModelId { get; set; }
public string ModelDescription { get; set; }
public string Manufacturer { get; set; }
public string EntityType { get; set; }
public IEnumerable<PartDto> PartList { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DBF_Models.Models
{
public class PartDto
{
public string SKU { get; set; }
public string Description { get; set; }
public int ModelId { get; set; }
public string EntityType = "Part";
public string Manufacturer { get; set; }
public string Class { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
namespace DBF_Models.Models
{
public class PartClassDto
{
public string ClassId { get; set; }
public string ClassDescription { get; set; }
}
}
Код, используемый для получения данных во вложенном Json
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Web.Http;
using System.Web.Http.Description;
using System.Web.UI.WebControls;
using DBF_Models;
using DBF_Models.Models;
namespace DBF_Models.Controllers
{
public class LinkedPartsController : ApiController
{
private ErpDevReplicationEntities db = new ErpDevReplicationEntities();
// GET: api/sp_fc_ModelList_test_Result
[Route("api/LinkedParts/All")]
public Object GetAll()
{
var models = db
.fc_Models
.Include("fc_LinkParts")
.Select(t => new ModelDto()
{
ModelSeq = t.ModelSeq,
ModelId = t.ModelId,
EntityType = "Model",
ModelDescription = t.ModelDesc,
Manufacturer = t.Manufacturer,
PartList = t.fc_LinkParts.Select(p => new PartDto()
{
EntityType = "Part",
ModelId = p.ModelSeq,
SKU = p.PartNum,
Description = p.PartDescription,
Manufacturer = p.Manufacturer,
Class = p.PartClass
})
});
return models;
}
Выход
[
{
"ModelSeq": 3020,
"ModelId": "ACW ",
"ModelDescription": "ACW ",
"Manufacturer": "Hobart Manufacturing Ltd",
"EntityType": "Model",
"PartList": [
{
"EntityType": "Part",
"SKU": "HOB01-240051-11 ",
"Description": "FILTER ",
"ModelId": 3020,
"Manufacturer": "Hobart Manufacturing Ltd",
"Class": "600"
},
{
"EntityType": "Part",
"SKU": "HOB104329 ",
"Description": "MECHANICAL SEAL ASSY 5/8\" ",
"ModelId": 3020,
"Manufacturer": "Hobart Manufacturing Ltd",
"Class": "186"
},
{
"EntityType": "Part",
"SKU": "HOB122674 ",
"Description": "FLOAT ASSEMBLY ",
"ModelId": 3020,
"Manufacturer": "Hobart Manufacturing Ltd",
"Class": "201"
},......
TLDR;
Это очевидно использует только таблицу 1 (fc_models) и таблицу 2 (fc_LinkParts)
Чего мне нужно добиться, так это ссылки в таблице PartClass или DTO, так что вместо класса вывода, как в Int, будет показано описание.
Желаемый выход
[
{
"ModelSeq": 3020,
"ModelId": "ACW ",
"ModelDescription": "ACW ",
"Manufacturer": "Hobart Manufacturing Ltd",
"EntityType": "Model",
"PartList": [
{
"EntityType": "Part",
"SKU": "HOB01-240051-11 ",
"Description": "FILTER ",
"ModelId": 3020,
"Manufacturer": "Hobart Manufacturing Ltd",
"Class": "Dishwasher"
},....
Я уверен, что решение будет простым и займет меньше времени, чем написание этого поста, но я озадачен кодом EF / Linq.
Спасибо за чтение
Решение: работает, но не уверен, что это лучший способ
Так с помощью пенлейчан
Я пытался использовать соединение, которое для меня имело смысл, и это было то, что я делал в SQL, но я просто не мог понять синтаксис или действительно, где его разместить.
Если бы это было в SQL, я бы вставил сюда
PartList = t.fc_LinkParts.Select(p => new PartDto()
{
EntityType = "Part",
ModelId = p.ModelSeq,
SKU = p.PartNum,
Description = p.PartDescription,
Manufacturer = p.Manufacturer,
Class = (from d in db.PartClasses
where d.ClassID == p.PartClass
select d.Description).FirstOrDefault()
}) "JOIN WOULD GO HERE"
, но просто не мог понять синтаксис, чтобы иметь возможность доступа ко всем полям, которые мне понадобятся для создания объединения.
Таким образом, решение, которое я нашел, я предполагаю, работает как подзапрос SQL. Я не уверен, так как не знаю, в какой SQL преобразован Linq.
// GET: api/sp_fc_ModelList_test_Result
[Route("api/LinkedParts/All")]
public Object GetAll()
{
var models = db
.fc_Models
.Include("fc_LinkParts")
.Select(t => new ModelDto()
{
ModelSeq = t.ModelSeq,
ModelId = t.ModelId,
EntityType = "Model",
ModelDescription = t.ModelDesc,
Manufacturer = t.Manufacturer,
PartList = t.fc_LinkParts.Select(p => new PartDto()
{
EntityType = "Part",
ModelId = p.ModelSeq,
SKU = p.PartNum,
Description = p.PartDescription,
Manufacturer = p.Manufacturer,
Class = (from d in db.PartClasses
where d.ClassID == p.PartClass
select d.Description).FirstOrDefault()
})
});
return models;
}
TLDR;
Это работает, но есть ли лучший способ?