根据外键 ID 将列值传递给来自不同 table 的模型
Pass a column value to model from a different table based on foreign key id
我有一个 products
table,它有一个 CategoryId
,代表 Categories
table.
中的相应主键
ProductViewModel
public ProductVM(ProductDTO productDTO)
{
Id = productDTO.Id;
Name = productDTO.Name;
Description = productDTO.Description;
Price = productDTO.Price;
CategoryId = productDTO.CategoryId;
ImageName = productDTO.ImageName;
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }
public int? CategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public string ImageName { get; set; }
public IEnumerable<string> GalleryImages { get; set; }
产品 DTO
public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}
这是我获得产品列表的方式:
List<ProductVM> productVM;
using (Db db = new Db())
{
productVM = db.Products
.ToArray()
.Select(x => new ProductVM(x))
.ToList();
}
如您所见,我正在传递 CategoryId
,我可以使用 ProductVM
ViewModel 在我的视图中显示它,但我也想获得 Name
类别也在那里。
我能想到一些技巧,例如基于 CategoryId
从 ViewModel
中的构造函数访问 DB
并以这种方式分配它,但我想看看是否有更优雅的解决方案?
底线 - 我的 Categories
table 中有一个 Name
列,我想以最有效的方式将该名称传递给 ProductVM
。
为类别名称添加一个 属性 模型,比如
public string CategoryName { get; set; }
并修改构造函数来填充它
public ProductVM(ProductDTO productDTO)
{
CategoryName = productDTO.Category.Name;
....
并将查询修改为
List<ProductVM> productVM = db.Products.AsEnumerable().Include(x => x.Category)
.Select(x => new ProductVM(x)).ToList();
请注意,如果您使用它进行编辑,您的视图模型还需要一个无参数构造函数,否则将在 POST 方法中抛出异常。
另请注意,您不需要 using (Db db = new Db())
最佳解决方案如下(我删除了所有其他答案)
namespace Test
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
internal class Program
{
private static void Main(string[] args)
{
List<ProductVM> productVM;
//It doesn't matter if you use a using block or not
using (Db db = new Db())
{
db.Database.Log = Console.WriteLine;//To see the generated SQL
productVM = db.Products
.Include(p => p.Category)
.Select(p => new ProductVM
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
Price = p.Price,
CategoryId = p.CategoryId,
CategoryName = p.Category.Name,
ImageName = p.ImageName,
}).ToList();
}
Console.ReadKey();
}
}
public class Db : DbContext
{
public DbSet<ProductDTO> Products { get; set; }
public DbSet<CategoryDTO> Categories { get; set; }
}
public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}
public class CategoryDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductVM
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }
public int? CategoryId { get; set; }
public string CategoryName { get; set; }
public string ImageName { get; set; }
}
}
我有一个 products
table,它有一个 CategoryId
,代表 Categories
table.
ProductViewModel
public ProductVM(ProductDTO productDTO)
{
Id = productDTO.Id;
Name = productDTO.Name;
Description = productDTO.Description;
Price = productDTO.Price;
CategoryId = productDTO.CategoryId;
ImageName = productDTO.ImageName;
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }
public int? CategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public string ImageName { get; set; }
public IEnumerable<string> GalleryImages { get; set; }
产品 DTO
public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}
这是我获得产品列表的方式:
List<ProductVM> productVM;
using (Db db = new Db())
{
productVM = db.Products
.ToArray()
.Select(x => new ProductVM(x))
.ToList();
}
如您所见,我正在传递 CategoryId
,我可以使用 ProductVM
ViewModel 在我的视图中显示它,但我也想获得 Name
类别也在那里。
我能想到一些技巧,例如基于 CategoryId
从 ViewModel
中的构造函数访问 DB
并以这种方式分配它,但我想看看是否有更优雅的解决方案?
底线 - 我的 Categories
table 中有一个 Name
列,我想以最有效的方式将该名称传递给 ProductVM
。
为类别名称添加一个 属性 模型,比如
public string CategoryName { get; set; }
并修改构造函数来填充它
public ProductVM(ProductDTO productDTO)
{
CategoryName = productDTO.Category.Name;
....
并将查询修改为
List<ProductVM> productVM = db.Products.AsEnumerable().Include(x => x.Category)
.Select(x => new ProductVM(x)).ToList();
请注意,如果您使用它进行编辑,您的视图模型还需要一个无参数构造函数,否则将在 POST 方法中抛出异常。
另请注意,您不需要 using (Db db = new Db())
最佳解决方案如下(我删除了所有其他答案)
namespace Test
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
internal class Program
{
private static void Main(string[] args)
{
List<ProductVM> productVM;
//It doesn't matter if you use a using block or not
using (Db db = new Db())
{
db.Database.Log = Console.WriteLine;//To see the generated SQL
productVM = db.Products
.Include(p => p.Category)
.Select(p => new ProductVM
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
Price = p.Price,
CategoryId = p.CategoryId,
CategoryName = p.Category.Name,
ImageName = p.ImageName,
}).ToList();
}
Console.ReadKey();
}
}
public class Db : DbContext
{
public DbSet<ProductDTO> Products { get; set; }
public DbSet<CategoryDTO> Categories { get; set; }
}
public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}
public class CategoryDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductVM
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }
public int? CategoryId { get; set; }
public string CategoryName { get; set; }
public string ImageName { get; set; }
}
}