Как скрыть элементы в ответе API из запроса базы данных? - PullRequest
1 голос
/ 01 апреля 2019

В настоящее время я использую MVC с EF, чтобы иметь небольшой сервер с 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);
}

И посев в программе.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 }

Из того, что я прочитал, это из-за ленивой загрузки, как я могу скрыть результат operatingDataItem?

В случае, если это невозможно, я, конечно, пытаюсь запросить его и вернуть обратно, и он выдаст что-то вроде:

{ "assetId":3,
  "assetName":"Test test",
  "odForeignKey":1,
  "operationalDataItem":
           { "operationalDataId":1,
             "comunity":"Comunity1",
             "assetItems":[

Но в этом случае я хотел бы скрыть "assetsItems" в ответе на FE. Как я могу скрыть эти параметры?

API довольно прост, просто пример кода:

var todoItem = await _context.AssetItems.FindAsync((Int32)id);
var item = _context.OperationalDataItems.Find((Int32)todoItem.OdForeignKey);
todoItem.OperationalDataItem = item;
return todoItem

1 Ответ

0 голосов
/ 01 апреля 2019

Если вы хотите получить данные из базы данных, но хотите получить только некоторые свойства, используйте Выбрать.Обычно это более эффективно, чем использование Find, потому что вы будете передавать только те данные, которые фактически планируете использовать.

Чтобы извлечь некоторые свойства assetItem, имеющий первичный ключ assetItemId:

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();

Или наоборот:

Извлечение нескольких свойств всех (или некоторых) элементов OperationalDataItems, каждое из которых имеет некоторые свойства всех (или некоторых) его AssetItems:

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] имеет определенное значение?Не лучше ли придерживаться соглашения о коде сущности, впервые принятого ?Это также устранит необходимость в большинстве атрибутов и / или свободно работающих 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.

...