简体   繁体   中英

Entity Framework : EF Designer from DB : Partial Class not working as expected

I do not understand why this works sometimes and sometimes not.

I am trying to configure partial class to add a few more fields, but the controller is not able to detect the new fields added to the partial class and the view throws the following error:

The associated metadata type for type 'WebApplication1.Models.Table' contains the following unknown properties or fields: countryList, selectedCountryList. Please make sure that the names of these members match the names of the properties on the main type.

So the problem is with the partial class. EF is not able to detect the new fields added to the partial class.

Model class generated by EF

namespace WebApplication1.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Table
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Gender { get; set; }
        public Nullable<bool> Java { get; set; }
        public Nullable<bool> Eng { get; set; }
        public string cityCode { get; set; }
    
        public virtual Country Country { get; set; }
    }
}

namespace WebApplication1.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Country
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Country()
        {
            this.Tables = new HashSet<Table>();
        }
    
        public long cityId { get; set; }
        public string cityCode { get; set; }
        public string cityName { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection<Table> Tables { get; set; }
    }
}

Partial class

namespace WebApplication1.Models
{
    [MetadataType(typeof(TableMetaData))]
    public partial class Table
    {
    }

    public class TableMetaData
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Gender { get; set; }
        public Nullable<bool> Java { get; set; }
        public Nullable<bool> Eng { get; set; }
        public string cityCode { get; set; }
    
        public virtual Country Country { get; set; }

        public SelectList countryList { get; set; }
        public string[] selectedCountryList { get;set; }
    }
}

This is my controller, the reason behind using viewBag.list is that the controller is not able to detect the partial class fields (ie countryList).

So, I am using ViewBag.list now but by right I should be using item.countryList

public ActionResult Create(int? id)
{
    ACDEntities1 db = new ACDEntities1();
    var item = db.Tables.Find(id);
    var CList = db.Countries.ToList();
    viewBag.countryList = new SelectList(CList, "CityCode", "cityName");
    //should use the following
    //item.countryList = new SelectList(CList, "CityCode", "cityName");

    return View(item);
}

View, here I am trying to use the field selectedCountryList of my partial class but it throws an error.

@Html.DropDownListFor(model => model.selectedCountryList, (IEnumerable<SelectListItem>)viewBag.countryList, "select city", new { @class = "form-control chosen-select", @multiple = true})

// should use this
// @Html.DropDownListFor(model => model.selectedCountryList, //(IEnumerable<SelectListItem>)Model.countryList, "select city", new { @class = "form-control //chosen-select", @multiple = true})

WORKING CODE

Partial class

namespace WebApplication1.Models
{
    [MetadataType(typeof(TableMetaData))]
    public partial class Table
    {
        [NotMapped]
        public SelectList countryList { get; set; }
        [NotMapped]
        public string[] selectedCountryList { get;set; }
    }

    public class TableMetaData
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Gender { get; set; }
        public Nullable<bool> Java { get; set; }
        public Nullable<bool> Eng { get; set; }
        public string cityCode { get; set; }
    
        public virtual Country Country { get; set; }

    }
}

I believe you're doing it wrong with your partial class. All the partial class parts from the various physical files they're specified in are joined together into one class definition - so your additional field must be in the partial class itself - not in the "metadata" class.

Try this:

namespace WebApplication1.Models
{
    public partial class Table
    {
        /* you cannot re-define those in your second "partial class" bit.....
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Gender { get; set; }
        public Nullable<bool> Java { get; set; }
        public Nullable<bool> Eng { get; set; }
        public string cityCode { get; set; }
    
        public virtual Country Country { get; set; }
        */ 

        public SelectList countryList { get; set; }
        public string[] selectedCountryList { get;set; }
    }
}

Since those partial parts are joined together - of course, you cannot have something defined in your hand-written part that's already defined in the generated part.

The [MetadataType(typeof(TableMetaData))] mechanism was designed to give you the opportunity to add additional metadata to an existing class (eg one that's code-generated) in order to add things like data annotations ( [Required] , [StringLength] etc.) - but that metadata mechanism isn't designed to extend the partial class and add additional properties to it

It's because of your partial class location and name create a folder named Partial or... and create your partial class with the exact name of the main class and place your custom properties in there

  • partial class name must be the exact name of main class
  • change the partial class namespace to WebApplication1.Models, not WebApplication1.Models.your folder name

Best regards

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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