简体   繁体   English

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

[英]Passing value from one model to another in a ViewModel

I am building my first MVC website and I am struggling to pass a value from one model to another in a ViewModel. 我正在构建我的第一个MVC网站,我正在努力在ViewModel中将值从一个模型传递到另一个模型。 The two classes are Music and MusicGenre. 这两个课程是Music and MusicGenre。 In Music, there is a field called 'GenreId' which is an int and is related to the 'Id' field in MusicGenres. 在Music中,有一个名为'GenreId'的字段,它是一个int,与MusicGenres中的'Id'字段相关。 I want to return the genre name relating to the Id that's passed over. 我想返回与传递的Id相关的类型名称。

Here's what I've got so far: 这是我到目前为止所得到的:

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

This all renders nicely minus displaying the right genre. 这一切都很好地减去显示正确的流派。 (I replaced xxx with Id but that just uses the id field from Music, not the GenreId field) (我用Id替换了xxx,但只使用了Music中的id字段,而不是GenreId字段)

So xxx is where I want to pass 'GenreId' but I don't know how. 所以xxx是我想传递'GenreId'但我不知道怎么做的地方。 Any help? 有帮助吗? Thanks 谢谢

To expand on my initial comment to the question, I'd just do something like: 为了扩展我对这个问题的初步评论,我只是做了类似的事情:

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

You should separate your view models from your persistence models. 您应该将视图模型与持久性模型分开。 View model is designed to display what you want to display to the users. 视图模型旨在显示您要向用户显示的内容。 Persistence model might reflect your data storage structures. 持久性模型可能反映您的数据存储结构。

Also from your example it looks like you might already have been using ORM like EntityFramework . 同样从您的示例看起来您可能已经使用了像EntityFramework这样的ORM。 EntityFramework provides features like navigation properties and lazy loading. EntityFramework提供导航属性和延迟加载等功能。

Either way, I strongly disagree accepted answer 's approach, which sends the music and its genre persistence models to the view, when you only need to get the genre name. 无论哪种方式,我强烈不同意接受的答案的方法,当你只需要获得流派名称时,它将音乐及其类型持久性模型发送到视图中。

Rather, I will approach it this way: 相反,我会这样做:

Persistence Models 持久性模型

You might have one-to-may relationship between a genre and an album in your persistence storage: 您可能在持久性存储中的类型和相册之间存在一对一的关系:

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; }
}

But obviously you don't want/need to reveal everything you have in your persistence storage to the user. 但显然您不希望/需要将持久存储中的所有内容透露给用户。 Hence you create view models and only contain what you want to display. 因此,您创建视图模型并包含要显示的内容。

View Models 查看模型

Let's say you have a view to display information about the selected album. 假设您有一个显示所选专辑信息的视图。 You might create a view model like this: 您可以创建这样的视图模型:

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

Then in the album controller, you can build the view model by using any ORM, lazy loading, etc: 然后在相册控制器中,您可以使用任何ORM,延迟加载等构建视图模型:

Controller 调节器

If you happen to use EntityFramework and have lazy loading enable, you can fetch genre name via its navigation property: 如果您碰巧使用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);
}

Now in a more advanced architecture, the read and write is separated, which is referred as CQRS. 现在,在更高级的体系结构中,读取和写入是分开的,称为CQRS。 For all the reads (ie, displaying information to the user), you can build your view model with data directly from executing plain SQL statement. 对于所有读取(即向用户显示信息),您可以直接从执行纯SQL语句构建包含数据的视图模型。

CQRS with Dapper CQS与Dapper

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM