Как получить модель представления, которая содержит две модели - PullRequest
1 голос
/ 11 марта 2019

В представлении мне нужна модель представления, которая содержит две модели.Я не знаю, как получить данные в хранилище.

Существует модель Products , которая имеет внешний ключ для другой модели.Вот моя ПРОДУКЦИЯ модель:

 public class Products
 {
    public int ProductId {get; set;}
    public string Productname {get; set;}
    public int ProductTypeID { get; set; }

    [ForeignKey("ProductTypeID")]
    public virtual ProductTypes ProductTypes { get; set; }
 }

А это моя PRODUCTTYPE модель:

 public class ProductTypes
 {
    public int ProductTypeId {get; set;}
    public int ProductTypeName {get; set;}
 }

Теперь я хочу использовать их в представлении, поэтому я создал модель представления

 public class ProductsViewModel
 {
    public Products Products { get; set; }
    public IEnumerable<ProductTypes>  ProductTypes { get; set; }

 }

Вот моя проблема.Я не знаю, как извлечь данные из модели представления в хранилище , например:

 public async Task<IEnumerable< XXX >> GetAllProducts()
 {
    return await _RepositoryContext.Set<xxx>.ToListAsync();
 } 

Наконец, это мой контроллер :

 public async Task<IActionResult> index()
 {
    return View(await ProductRepository.GetAllProducts());
 }

Ответы [ 3 ]

1 голос
/ 11 марта 2019

В вашем репозитории вы используете выражение вроде этого

public async Task<IEnumerable< Products >> GetAllProducts()
 {
var products =   _RepositoryContext.Set<Products> ();
return await products.include(x =>x.ProductType).ToListAsync();
}

Но я думаю, что вам нужно изменить ваши модели. вы возвращаете доменные классы в контроллер как представление модели, что не очень хорошая идея, у вас должны быть отдельные классы модели и вы должны использовать Automapper для отображения домена на классы модели, чтобы на стороне клиента вы отправляли только классы модели, которые могут иметь много дополнительных столбцов, чем доменные классы. Вот как должны выглядеть ваши классы моделей

public class Products
 {
    public int ProductId {get; set;}
    public string Productname {get; set;}
    public int ProductTypeID { get; set; }

    [ForeignKey("ProductTypeID")]
    public virtual ProductTypes ProductTypes { get; set; }
 }
public class ProductTypes
 {
    public int ProductTypeId {get; set;}
    public int ProductTypeName {get; set;}
 }

Теперь модели должны быть такими

public class ProductsModel
 {
    public int ProductId {get; set;}
    public string Productname {get; set;}
    public int ProductTypeID { get; set; }
    public virtual ProductTypesModel  ProductTypes { get; set; }
    public string  ProductTypeName {get; set;}
 }

public class ProductTypesModel
 {
    public int ProductTypeId {get; set;}
    public int ProductTypeName {get; set;}
 }

Теперь метод репозитория должен выглядеть следующим образом

public async Task<IEnumerable< Products >> GetAllProducts()
 {
var  products = _RepositoryContext.Set<Products> ();
return await products.include(x =>x.ProductType).ToListAsync();

}

Наконец, это будет ваш контроллер Контроллер,

 public async Task<IActionResult> index()
 {
  var productList=   await ProductRepository.GetAllProducts() 
  var ProductModels =  Mapper.Map<IEnumerable<Products>, IEnumerable<ProductsModel>>( productList)
    return View(ProductModels);
 }

Чтобы узнать, как настроить AutoMapper, обратитесь к этому посту, Как настроить Automapper в ASP.NET Core

0 голосов
/ 11 марта 2019

Это зависит от того, что вы на самом деле хотите сделать в своем представлении: предполагается, что модель представления содержит именно те данные, которые необходимы для отображения представления.Обычно вы не хотели бы включать туда больше данных.Поэтому использование моделей базы данных внутри модели представления не лучший выбор;было бы лучше спроектировать реальные модели представлений, которые соответствуют отображаемому материалу, и затем вы решите, как правильно получить эти данные.

Исходя из того, как выглядит ваша модель представления, я мог бы предположить два варианта использования:

  1. Вы хотите отобразить набор продуктов и перечислить те типы продуктов, которые имеют этот набор продуктов.
  2. Вы хотите отобразить набор продуктов и список все типы продуктов.

Вариант 2 действительно прост и требует, чтобы вы запрашивали каждый тип сущности только один раз:

var viewModel = new ProductsViewModel
{
    Products = await db.Products.ToListAsync(),
    ProductTypes = await db.ProductTypes.ToListAsync(),
};

Вариант 1 можно наивно решить, включив продуктвводится через свойство навигации в сущности Product:

var products = await db.Products.Include(p => p.ProductType).ToListAsync();

var viewModel = new ProductsViewModel
{
    Products = products,
    ProductTypes = products.Select(p => p.ProductType).Distinct().ToList(),
};

Однако это имеет недостаток, заключающийся в том, что при наличии нескольких отдельных типов продуктов вы будете загружать каждый тип продукта несколько раз.Поскольку тип вашего продукта имеет только идентификатор и имя, это не , что проблематично, а для более сложных типов может быть.

Другой подход заключается всначала запросите идентификаторы типов продуктов из списка продуктов, а затем загрузите типы продуктов:

var products = await db.Products.Include(p => p.ProductType).ToListAsync();
var productTypeIds = product.Select(p => p.ProductTypeId).Distinct().ToList();

var viewModel = new ProductsViewModel
{
    Products = products,
    ProductTypes = await db.ProductTypes.Select(t => productTypeIds.Contains(t.Id)).ToListAsync(),
};

Два примечания:

  1. Я проигнорировал существование вашегорепозиторий здесь и просто предполагается, что вы используете EntityFramework DbContext здесь.Если вы хотите абстрагировать это в хранилище, вы можете сделать это.
  2. Сущность с именем Products, но содержит информацию только об одном продукте.Аналогично, модель представления содержит свойство Products того же типа.Это не имеет большого смысла для меня, поэтому я просто предположил, что сущность называется Product и представляет отдельный элемент, в то время как ProductsViewModel имеет Products, список Product.
0 голосов
/ 11 марта 2019

Все зависит от вашей архитектуры. Тем не менее, хранилище может быть не лучшим местом для сопоставления между моделями и моделями представления, поскольку после изменения ORM хранилище также может быть изменено, в то время как это сопоставление может быть где-то во избежание ненужных изменений. Я лично предпочитаю делать сопоставление либо в BLL, либо в самой viewmodel без использования AutoMapper. Вот один из возможных способов отображения в моделях представления:

public class ProductsDto
{
    public int ProductId { get; set; }
    public string Productname { get; set; }
    public virtual ProductTypeDto ProductTypes { get; set; }
    public void SetDto(Products obj)
    {
        if (obj == null)
            return;
        this.ProductId = obj.ProductId;
        this.Productname = obj.Productname;
        if (obj.ProductTypes != null)
        {
            this.ProductTypes = new ProductTypeDto();
            this.ProductTypes.SetDto(obj.City);
        }
    }
}

public class ProductTypeDto
{
    public int ProductTypeId { get; set; }
    public int ProductTypeName { get; set; }
    public void SetDto(ProductType obj)
    {
        if (obj == null)
            return;
        this.ProductTypeId = obj.ProductTypeId;
        this.ProductTypeName = obj.ProductTypeName;
    }
}

Использование viewmodels:

 public ProductsDto GetProductsDto(Products obj)
    {
        var dto = new ProductsDto();
        dto.SetDto(obj);
        return dto;
    }
----------------------------------------------------------
    var products = _RepositoryContext.Products.ToList();
    var productsDto = products?.Select(GetProductsDto);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...