在ViewModel中将值从一个模型传递到另一个模型

时间:2019-05-08 22:19:24

标签: c# asp.net-mvc linq

我正在建立我的第一个MVC网站,并且正在努力将值从一个模型传递到ViewModel中的另一个模型。这两个类是Music和MusicGenre。在音乐中,有一个名为'GenreId'的字段,它是一个整数,与MusicGenres中的'Id'字段相关。我想返回与所传递的ID相关的流派名称。

这是到目前为止我得到的:

        MusicViewModel vmMusic = new MusicViewModel
        {
            Music = _context.Music.SingleOrDefault(c => c.Id == id),
            MusicGenres = _context.MusicGenres.Where(gi => gi.Id == xxx).ToList()
        };
        return View(vmMusic); 

所有这些都很好地减去了显示正确类型的内容。 (我用Id替换了xxx,但只使用了Music中的id字段,而不是GenreId字段)

所以xxx是我想传递'GenreId'的地方,但我不知道如何。有什么帮助吗? 谢谢

2 个答案:

答案 0 :(得分:0)

要扩展我对该问题的最初评论,我会做类似的事情:

    var music = _context.Music.SingleOrDefault(c => c.Id == id);
    var musicGenres = _context.MusicGenres.Where(gi => gi.Id == music.GenreId).ToList(); // whatever the genre id property is called.
    MusicViewModel vmMusic = new MusicViewModel
    {
        Music = music,
        MusicGenres = musicGenre
    };
    return View(vmMusic); 

答案 1 :(得分:0)

您应该将视图模型与持久性模型分开。视图模型旨在向用户显示您要显示的内容。持久性模型可能反映了您的数据存储结构。

从您的示例中还可以看出,您可能已经在使用EntityFramework之类的ORM。 EntityFramework提供了诸如导航属性和延迟加载之类的功能。

无论哪种方式,我都强烈不同意接受的答案的方法,该方法将音乐及其流派 persistence 模型发送到视图,而您只需要获取流派名称。

相反,我将以这种方式进行处理:

持久性模型

持久性存储中的流派和专辑之间可能存在一对一的关系:

public class Album
{
    public int AlbumId { get; set; }
    public string Title { get; set; }
    public double Price { get; set; }

    public int GenreId { get; set; }
    public Genre Genre { get; set; }
}

public class Genre
{
    public int GenreId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public List<Album> Albums { get; set; }
}

但是显然,您不想/不需要向用户显示持久性存储中的所有内容。因此,您可以创建视图模型,并且包含要显示的内容。

查看模型

假设您有一个视图来显示有关所选专辑的信息。您可以这样创建一个视图模型:

public class AlbumViewModel
{
    public int AlbumId { get; set; }
    public string AlbumName { get; set; }
    public string Genre { get; set; }
}

然后在相册控制器中,您可以使用任何ORM,延迟加载等来构建视图模型:

控制器

如果您碰巧使用EntityFramework并启用了延迟加载,则可以通过其导航属性获取流派名称:

public ActionResult Details(int id)
{
    var album = _dbContext.Albums.SingleOrDefault(x => x.AlbumId == id);
    if (album == null)
    {
        return HttpNotFound();
    }

    var vm = new AlbumViewModel
    {
        AlbumId = album.AlbumId,
        AlbumName = album.Title,

        // You can get the genre name via Navigation property, and/or lazy
        // loading
        Genre = album.Genre.Name
    };

    return View(vm);
}

现在,在更高级的体系结构中,读写是分开的,即  称为CQRS。对于所有读取(即向用户显示信息),您可以直接从执行普通SQL语句的数据中构建视图模型。

带有Dapper的CQRS

using Dapper;
using System.Data;

...

public class AlbumController : Controller
{
    private readonly IDbConnection _dbConnection;

    public AlbumController(IDbConnection dbConnection)
    {
        _dbConnection = dbConnection;
    }

    public ActionResult Details(int id)
    {
        const string sql = @"
SELECT a.AlbumId, a.Title AS [AlbumName], g.Name AS [Genre]
FROM [Album] a
    JOIN [Genre] g ON a.GenreId = g.GenreId
WHERE a.AlbumId = @albumId;
";

        var vm = _dbConnection.QuerySingleOrDefault<AlbumViewModel>(sql, new {
            albumId = id
        });
        if (vm == null)
        {
           return HttpNotFound();
        }

        return View(vm);
    }
}