0

from the answers given on my previous question topic: mvc database first issues with edmx/relationships and view showing id field, i realized that the viewmodel is the way to go, so i'll post my viewmodel related questions here.

first up, the edmx is the following

enter image description here

my database constraints are that 1 book may multiple authors and multiple publishers

these are my current classes:

BOOK

public partial class BOOK
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public BOOK()
    {
        this.AUTHORS = new HashSet<AUTHOR>();
        this.PUBLISHERS = new HashSet<PUBLISHER>();
    }

    public int ID { get; set; }
    public string TITLE { get; set; }
    public int PAGES { get; set; }
    public string SYNOPSIS { get; set; }
    public System.DateTime PUBLISHDATE { get; set; }
    public string ISBN { get; set; }
    public string SUBJECT { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<AUTHOR> AUTHORS { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<PUBLISHER> PUBLISHERS { get; set; }
}

PUBLISHER

public partial class PUBLISHER
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public PUBLISHER()
    {
        this.BOOKS = new HashSet<BOOK>();
    }

    public int ID { get; set; }
    public string COUNTRY { get; set; }
    public string NAME { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<BOOK> BOOKS { get; set; }
}

AUTHOR

public partial class AUTHOR
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public AUTHOR()
    {
        this.BOOKS = new HashSet<BOOK>();
    }

    public int ID { get; set; }
    public string FIRSTNAME { get; set; }
    public string LASTNAME { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<BOOK> BOOKS { get; set; }
}

right now i can successfully save book records, however they only have 1 author and 1 publisher, how can i accomplish multiple authors and publishers?

my view model:

public class BooksViewModel
{
    [Key]
    public int ID { get; set; }
    [Display(Name = "Title")]
    public string TITLE { get; set; }
    [Display(Name = "Pages")]
    public int PAGES { get; set; }
    [Display(Name = "Synopsis")]
    public string SYNOPSIS { get; set; }
    [Display(Name = "Publish Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime PUBLISHDATE { get; set; }
    [Display(Name = "ISBN")]
    public string ISBN { get; set; }
    [Display(Name = "Subject")]
    public string SUBJECT { get; set; }
    [Display(Name = "Publisher")]
    public string NAME { get; set; }
    [Display(Name = "Publisher Location")]
    public string COUNTRY { get; set; }
    [Display(Name = "Auhor First Name")]
    public string FIRSTNAME { get; set; }
    [Display(Name = "Author Last Name")]
    public string LASTNAME { get; set; }

}

should i change the string properties regarding authors and publishers to lists of those objects? i.e

public class BooksViewModel2
{
    [Key]
    public int ID { get; set; }
    [Display(Name = "Title")]
    public string TITLE { get; set; }
    [Display(Name = "Pages")]
    public int PAGES { get; set; }
    [Display(Name = "Synopsis")]
    public string SYNOPSIS { get; set; }
    [Display(Name = "Publish Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime PUBLISHDATE { get; set; }
    [Display(Name = "ISBN")]
    public string ISBN { get; set; }
    [Display(Name = "Subject")]
    public string SUBJECT { get; set; }

    public virtual ICollection<AUTHOR> AUTHORS { get; set; }
    public virtual ICollection<PUBLISHER> PUBLISHERS { get; set; }

}

and on the view just do a for cycle using this property and then simply add columns to the table within the page?

i'll post my index and create actions' of the viewmodel for your appreciation

index action:

private ApplicationDbContext db = new ApplicationDbContext();

    // GET: BooksViewModels
    public ActionResult Index()
    {
        return View(db.BooksViewModels.ToList());
    }

create action:

public ActionResult Create([Bind(Include = "ID,TITLE,PAGES,SYNOPSIS,PUBLISHDATE,ISBN,SUBJECT,NAME,COUNTRY,FIRSTNAME,LASTNAME")] BooksViewModel booksViewModel)
    {
        if (ModelState.IsValid)
        {

            BOOK new_book = null;
            var new_author = new List<AUTHOR>(){};
            new_author.Add(new AUTHOR() { FIRSTNAME = booksViewModel.FIRSTNAME, LASTNAME = booksViewModel.LASTNAME });

            var new_publisher = new List<PUBLISHER>() { };
            new_publisher.Add(new PUBLISHER() { COUNTRY = booksViewModel.COUNTRY, NAME = booksViewModel.NAME });

            using (ApplicationDbContext db = new ApplicationDbContext())
            {
                new_book = new BOOK()
                {
                    ID = booksViewModel.ID,
                    TITLE = booksViewModel.TITLE,
                    PAGES = booksViewModel.PAGES,
                    SYNOPSIS = booksViewModel.SYNOPSIS,
                    PUBLISHDATE = booksViewModel.PUBLISHDATE,
                    ISBN = booksViewModel.ISBN,
                    SUBJECT = booksViewModel.SUBJECT,
                    AUTHORS  = new_author,
                    PUBLISHERS = new_publisher
                };                 
            }

//database context
            using (LibrarySQLEntities db2 = new LibrarySQLEntities())
            {
                db2.BOOKS.Add(new_book);
                db2.SaveChanges();
            }
//viewmodel context
            using (ApplicationDbContext db = new ApplicationDbContext())
            {
                db.BooksViewModels.Add(booksViewModel);
                db.SaveChanges();
            }

        }
        return RedirectToAction("Index");
    }

i have the following questions about the code above:

  1. is it correct to save changes made to both the viewmodel context and database context instead of just saving the data directly onto the database context and then have the viewmodel index action get the data directly from the database context?
  2. if the answer to question 1 is affirmative, how do i populate my viewmodel with database data?
Community
  • 1
  • 1
user2983177
  • 201
  • 2
  • 6
  • 18
  • If your wanting to add/edit/remove collections of authors and publishers in `Book`, then your view model needs to contain collections for those objects. Refer the answers [here](http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796) and [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) for some options for editing (and remove that awful `[Bind]` attribute - you never need that when using a view model) –  Jan 19 '16 at 22:48
  • And you do not have a context for your view model. When you submit the form you map the properties of the view model to a new (or existing) instance of a data model. I suggest you read [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) –  Jan 19 '16 at 22:50
  • for saving data of Book , yo don't need to do `using (ApplicationDbContext db = new ApplicationDbContext()) { db.BooksViewModels.Add(booksViewModel); db.SaveChanges(); }` the first part is enough for that. – Viplock Jan 20 '16 at 09:28
  • please tell , if a book is having more then one author then how you gonna receive the data from view for that. ? as per my suggestion, Make multi select dropdown of Author,publisher and get the data from View. – Viplock Jan 20 '16 at 09:31
  • @Viplock i was thinking about defining the view model like BooksViewModel2 and then on the view adding 2 text inputs for the author's first and last name and then use jquery to add inputs for multiple authors – user2983177 Jan 20 '16 at 17:23
  • Author is your primary tables , you should not add data in it by this way . in this case while adding book you will provide author name and it will be saving data in BookAuthor table and author table . By this way same author can be added mutiple times in Author table while adding 2 books . – Viplock Jan 20 '16 at 17:34

0 Answers0