我目前正在使用带有EF的MVC来使用一个带有API查询SQL数据库的小型服务器。但是在API回复中我无法隐藏一些参数。
主要对象
public class AssetItem
{
[Key]
public Int32 AssetId { get; set; }
public String AssetName { get; set; }
public int OdForeignKey { get; set; }
[ForeignKey("OdForeignKey")]
public OperationalDataItem OperationalDataItem { get; set; }
}
另一个:
public class OperationalDataItem
{
[Key]
public Int32 OperationalDataId { get; set; }
public String Comunity { get; set; }
public List<AssetItem> AssetItems { get; set; }
}
从我读过的,这应该没问题,我也设置了上下文:
public AssetContext(DbContextOptions<AssetContext> options) : base(options)
{}
public DbSet<AssetItem> AssetItems { get; set; }
public DbSet<OperationalDataItem> OperationalDataItems { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AssetItem>().HasOne(p =>
p.OperationalDataItem).WithMany(b => b.AssetItems).HasForeignKey(p =>
p.OdForeignKey);
}
并且在program.cs中播种
context.AssetItems.Add(
new AssetItem { AssetName = "Test test", OdForeignKey = 1,
OperationalDataItem =
new OperationalDataItem {Comunity = "Comunity1" }});
所以调用API会导致:
{ "assetId":3,
"assetName":"Test test",
"odForeignKey":1,
"operationalDataItem":null }
从我读到的这是因为延迟加载,我如何隐藏结果operationalDataItem?
如果不可能,我当然会尝试查询它并将其还给它,它给出了类似的东西:
{ "assetId":3,
"assetName":"Test test",
"odForeignKey":1,
"operationalDataItem":
{ "operationalDataId":1,
"comunity":"Comunity1",
"assetItems":[
但在这种情况下,我想在FE的回复中隐藏“assetsItems”。我该如何隐藏这些参数?
API非常简单,只是一个示例代码:
var todoItem = await _context.AssetItems.FindAsync((Int32)id);
var item = _context.OperationalDataItems.Find((Int32)todoItem.OdForeignKey);
todoItem.OperationalDataItem = item;
return todoItem
如果要从数据库中获取数据,但只想获取某些属性,请使用“选择”。通常这比使用Find更有效,因为您只会传输实际计划使用的数据。
要获取具有主键assetItemId的assetItem的某些属性:
var result = dbContext.AssetItems
.Where(assetItem => assetItem.AssetItmId = assetItemId)
.Select(assetItem => new
{
// Select only the properties that you plan to use
Id = assetItem.AssertItemId,
Name = assetItem.Name,
OperationalData = new
{
// again, select only the properties that you plan to use
Id = assetItem.OperationalData.OperationalDataId,
Community = assetItem.OperationalData.Community,
},
})
.FirstOrDefault();
或者反过来说:
获取所有(或一些)OperationalDataItem的几个属性,每个属性都包含其所有(或部分)AssetItem的一些属性:
var result = dbContext.OperqationalDataItems
.Where(operationalDataItem => ...) // only if you don't want all
.Select(operationalDataItem => new
{
Id = operationalDataItem.Id,
Community = operationalDataItem.Community
AssetItems = operationalDataItem.AssetItems
.Where(assetItem => ...) // only if you don't want all its assetItems
.Select(assetItem => new
{
// Select only the properties you plan to use:
Id = assetItem.Id,
...
// not useful: you know the value of the foreign key:
// OperationalDataId = assetItem.OperationalDataId,
})
.ToList();
})
.ToList(); // or: FirstOrDefault if you expect only one element
实体框架知道您的一对多关系,并且足够聪明,可以知道查询需要哪个(组)连接。
有些方面的评论
你已经宣布你的多关系是List<AssetItem>
。你确定operationalDataItem.AssetItems[4]
有明确的含义吗?坚持entity framework code first conventions不是更好吗?这也将消除对大多数属性和/或流畅API的需求
public class OperationalDataItem
{
public int Id { get; set; }
public String Comunity { get; set; }
...
// Every OperationalDataItem has zero or more AssetItems (one-to-many)
public virtual ICollection<AssetItem> AssetItems { get; set; }
}
public class AssetItem
{
public int Id { get; set; }
public String Name { get; set; }
...
// every AssetItem belongs to exactly one OperationalDataItem, using foreign key
public int OperationDataItemId { get; set; }
public virtual OperationalDataItem OperationalDataItem { get; set; }
}
在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系(一对多,多对多)
因为我坚持惯例,所以不需要属性或流畅的API。实体框架能够检测一对多关系以及主键和外键。只有当我对列的名称或类型不满意时,我才需要流畅的API。