【问题标题】:C# How to add value to ViewModelC# 如何为 ViewModel 添加价值
【发布时间】:2025-12-15 23:15:01
【问题描述】:

我将尝试解释我正在尝试做的事情 - 目前我为我正在使用的每个表格都有一个模型,并且一个 ViewModel 只包含表格内容的一部分。

我还向 ModelView 添加了一个或两个额外的属性,它来自另一个表。我的问题是,如何将值(我有一个可以为我带来该属性的函数)分配给 viewModel 对象?

视图模型:

public class StreetViewModel
{
    public Int64 Id { get; set; }
    public Int64 CityId { get; set; }
    public string Name { get; set; }
    public string CityName { get; set; } // THIS IS THE EXTRA PROPERTY
}

我的控制器动作来分配对象:

public IActionResult GetStreetByName(string streetName)
{
        var results = _repository.GetStreetByName(streetName); //Return a list of object of type Street
        return Ok(Mapper.Map<IEnumerable<StreetViewModel>>(results)); // convert Street object to STREETVIEWMODEL object and return it.
}

我的GetStreetByName 方法:

public IEnumerable<Street> GetStreetByName(string streetName)
{
    return _context.Street.Where(t => t.Name.Contains(streetName)).ToList();
}

此方法将为我返回一个对象类型 Street 的列表,在我拥有的每个 CityId 中,我还想选择仅出现在 City 表中的 CityName

我还有一个通过 ID 获取城市对象的方法:

public City GetCityNameById(int cityId)
{
    return _context.City.Where(t => t.Id == cityId).FirstOrDefault();
}

在哪里以及如何为 Street 的每条记录分配一个 cityName ?

【问题讨论】:

  • 你在使用 AutoMapper 吗?
  • 是的,我是@FelipeOriani
  • 您应该使用 ProjectTo,而不是 Map。 docs.

标签: c# sql-server asp.net-mvc database


【解决方案1】:

如果您使用的是AutoMapper,按照本工具的本地约定,您可以使用TDestionation 上的属性名称来导航属性,例如。假设您有这些实体:

public class City
{
   public string Name { get; set; }
}

public class Street 
{
   public City City { get; set; }
}

然后,当您在 StreetViewModel 上定义名为 CityName 的属性时,AutoMapper 将在您的 TSource 上查找名为 CityName 的属性,但不会找到。然后,它将尝试查看City,它会在名为Name 的属性之后找到。这是autoMapper对属性名大小写的约定,请注意。

AutoMapper - 自定义映射

另一方面,您可以在映射上配置它。示例:

config.CreateMap<Street, StreetViewModel>()
   .ForMember(t => t.CityName, opt => opt.MapFrom(x => x.City.Name));

重要 - SELECT N+1 问题

请记住在使用ORM(实体框架或NHibernate)在数据库上进行查询时获取City 属性以避免延迟加载。如果Street 结果集上有很多记录,则会导致SELECT N+1 problem。在Entity Framework 中,您可以使用Include,在NHibernate 中,您可以使用Fetch

【讨论】:

  • 问题 - 我的GetStreetByName 方法是选择街道列表。 Automapper 会通过CityId 自动将它们每个附加到正确的城市吗?或者这个附件是如何发生的(我的数据库有关系,但我的项目没有,我只是基于我的数据库创建了类并且没有从另一个创建它们)。而且,我不明白你所说的“取城……”是什么意思,究竟是什么意思?我对 .net 和 c# 还很陌生,对于初学者的问题,我很抱歉
  • Fetch the city,意思是当ORM工具在数据库中命中查询时,会在同一个街道查询中生成一个join,从city中取出数据。如果您不这样做,它将执行延迟加载以获取城市名称。
  • 好的,那么,我怎样才能使用实体框架来建立这种关系呢?正如我所说,我在 VS 中从头开始创建它们,尽管它们已经存在于数据库中。那么我在哪里指定关系? city.id -&gt; street.cityId