Model compatibility cannot be checked because the database does not contain model metadata. Model - entity-framework-4

I a tiring to upload excel sheet and insert data in MySQL database.
when I debug I am getting below error:
Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.
Below my code:
enter code here
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
Database.SetInitializer<EFDbContext>(new UploadUsingEntity.Domain.Concrete.ExcelStructureInitializer());
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
AuthConfig.RegisterAuth();
}
helper class
public DataSet ReadExcelFile(string filePath, out string msg, string isHDR = "Yes")
{
string details = string.Empty;
List<Excelstructure> lstEntityTable = repository.ExcelStructure.Where(
x => x.File_Name.Equals("EmployeeExcel", StringComparison.InvariantCultureIgnoreCase)).
OrderBy(x => x.Row_No).ToList();
List<string> lstFieldType = new List<string>();
lstFieldType.AddRange(lstEntityTable[1].Field_Data.ToString().Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries));
DataTable dt = CreateDataTableFromList(lstEntityTable);
DataSet ds = GetDataFromMultipleSheets(filePath, lstFieldType);
string fileName = string.Empty;
for (byte i = 0; i < ds.Tables.Count; i++)
{
if (ds.Tables[i].Rows.Count > 0)
{
details = ValidateExcelHeadings(dt, ds.Tables[i]);
ds.DataSetName = filePath.Substring(filePath.LastIndexOf("\\") + 1);
}
}
msg = details;
return ds;
}
ExcelStructure entites
[Table("ExcelStructure")]
public class Excelstructure
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Row_ID { get; set; }
public int File_ID { get; set; }
public string File_Name { get; set; }
public string Field_Name { get; set; }
public string Field_Data { get; set; }
public int Active_Flag { get; set; }
public int Row_No { get; set; }
public string Field_Delimeter { get; set; }
}
outstanding entites
[Table("outstanding")]
public class oustanding
{
[Key]
public string CustomerID { get; set; }
public string Name { get; set; }
public long PhoneNumber { get; set; }
public string Address { get; set; }
public int ServiceProviderID { get; set; }
public string TotalDue { get; set; }
public string LastPaidAmount { get; set; }
public Nullable<System.DateTime> LastPaidDate { get; set; }
public string OutStandingDescription { get; set; }
public string longitudeandlatitude { get; set; }
}
public class ExcelStructureInitializer : DropCreateDatabaseIfModelChanges<EFDbContext>
{
protected override void Seed(EFDbContext context)
{
//base.Seed(context);
var excelStructure = new List<Excelstructure>()
{
new Excelstructure(){ File_ID=1, Field_Name="outstanding", Field_Data="CustomerID|Name|PhoneNumber|Address|ServiceProviderID|TotalDue|LastPaidAmount|LastPaidDate|OutStandingDescription|longitudeandlatitude", Active_Flag=1, Row_No=1, File_Name="oustanding", Field_Delimeter="|"},
new Excelstructure(){ File_ID=1, Field_Name="DataType", Field_Data="S|S|I|S|I|S|S|D|S|S", Active_Flag=1, Row_No=2, File_Name="outstanding", Field_Delimeter="|"},
new Excelstructure(){ File_ID=1, Field_Name="Size", Field_Data="50|100|20|100|10|100|100|20|100|100", Active_Flag=1, Row_No=3, File_Name="outstanding", Field_Delimeter="|"},
new Excelstructure(){ File_ID=1, Field_Name="Mandatory", Field_Data="Y|Y|Y|Y|Y|N|N|N|N|N", Active_Flag=1, Row_No=4, File_Name="outstanding", Field_Delimeter="|"},
new Excelstructure(){ File_ID=1, Field_Name="Param", Field_Data="#CustomerID|#Name|#PhoneNumber|#Address|#ServiceProviderID|#TotalDue|#LastPaidAmount|#LastPaidDate|#OutStandingDescription|#longitudeandlatitude", Active_Flag=1, Row_No=5, File_Name="outstanding", Field_Delimeter="|"},
};
context.ExcelStructure.AddRange(excelStructure);
context.SaveChanges();
}
}

What this error implicates is that the database was not created by Entity Framework so it cannot make sure whether your model can be used with this database. The reason is most likely that you've created the database with the script in the article:
CREATE TABLE [dbo].[ExcelStructure] ....
However the ExcelStructureInitializer will take care of the creation of your database so delete the database and leave it to the initializer to create the structure and the seed data.
By the way if you want to support production code you should consider Migrations instead of a Database Initializer.

Related

How to implement Create with child collection in Application Layer?

I have 2 entities named News and NewsAttachment in the .Core Project. These entities have a relationship through News_Id. In other words, when I create new News and add it into database, this News may have one or two attachment media that I want to insert in the related table named NewsAttachment. So I may want to retrieve News_Id and insert attachments in the related table.
I define 2 DTOs named NewsDto and CreateNewsDto in NewsAppService and I pass CreateNewsDto to insert new News, but I have no idea how to do it for NewsAttachment.
Here is my News entity:
public class News : FullAuditedEntity<long>
{
public const int MaxTitleLength = 150;
public const int MaxContentLength = 1200;
public const int MaxMetaTagLength = 60;
[Required]
[MaxLength(MaxTitleLength)]
public string Title { get; set; }
[Required]
public string Code { get; set; }
[Required]
[MaxLength(MaxContentLength)]
public string Content { get; set; }
public DateTime PublishDate { get; set; }
[MaxLength(MaxMetaTagLength)]
public string Tags { get; set; }
public virtual NewsType Type { get; set; }
public virtual ICollection<NewsAttachment> Attachments { get; set; }
}
and NewsAttachment entity:
public class NewsAttachment: FullAuditedEntity<long>
{
public const int MaxTitleLength = 50;
[Required]
[MaxLength(MaxTitleLength)]
public string FileName { get; set; }
[Required]
public byte[] File { get; set; }
public string FileExtension { get; set; }
public int FileSize { get; set; }
[Required]
public DateTime RegisterDate { get; set; }
public virtual News News { get; set; }
}
and the DTOs:
public class NewsDto : EntityDto<long>
{
public const int MaxTitleLength = 50;
public const int MaxContentLength = 800;
public const int MaxMetaTagLength = 60;
[Required]
[MaxLength(MaxTitleLength)]
public string Title { get; set; }
[Required]
public string Code { get; set; }
[Required]
[MaxLength(MaxContentLength)]
public string Content { get; set; }
public DateTime PublishDate { get; set; }
[MaxLength(MaxMetaTagLength)]
public string Tags { get; set; }
public virtual NewsType Type { get; set; }
}
and:
public class CreateNewsDto
{
public const int MaxTitleLength = 50;
public const int MaxContentLength = 800;
public const int MaxMetaTagLength = 60;
[Required]
[MaxLength(MaxTitleLength)]
public string Title { get; set; }
[Required]
public string Code { get; set; }
[Required]
[MaxLength(MaxContentLength)]
public string Content { get; set; }
public DateTime PublishDate { get; set; }
[MaxLength(MaxMetaTagLength)]
public string Tags { get; set; }
public virtual NewsType Type { get; set; }
public virtual ICollection<NewsAttachment> Attachments { get; set; }
}
Here is my presumptive method in NewsAppService to insert new News and add related media to NewsAttachment table:
public virtual NewsDto InsertWithMedia(CreateNewsDto input, NewsAttachmentDto attach)
{
var news = ObjectMapper.Map<NewsManagement.News>(input);
var newsAttachment = ObjectMapper.Map<NewsAttachment>(attach);
newsAttachment.News.Id = news.Id;
return MapToEntityDto(news);
}
Two choices:
Add to ICollection and let EF handle the entities:
public virtual NewsDto InsertWithMedia(CreateNewsDto input, NewsAttachmentDto attach)
{
var news = ObjectMapper.Map<NewsManagement.News>(input);
news.Attachments = new List<NewsAttachment>(); // 1
var newsAttachment = ObjectMapper.Map<NewsAttachment>(attach);
news.Attachments.Add(newsAttachment); // 2
_newsRepository.Insert(news); // 3
CurrentUnitOfWork.SaveChanges(); // 4
return MapToEntityDto(news);
}
Add by Id instead of collection, with a foreign key:
public class NewsAttachment: FullAuditedEntity<long>
{
// ...
public virtual long NewsId { get; set; }
public virtual News News { get; set; }
}
public virtual NewsDto InsertWithMedia(CreateNewsDto input, NewsAttachmentDto attach)
{
var news = ObjectMapper.Map<NewsManagement.News>(input);
var newsId = _newsRepository.InsertAndGetId(news); // 1
var newsAttachment = ObjectMapper.Map<NewsAttachment>(attach);
newsAttachment.NewsId = newsId; // 2
_newsAttachmentRepository.Insert(newsAttachment); // 3
CurrentUnitOfWork.SaveChanges(); // 4
return MapToEntityDto(news);
}
The second is good for updating — when newsId is already known — but may require additional steps if NewsDto also has Attachments (which should be ICollection<AttachmentDto> type).
thank you #aaron. after all, I have a little problem. in .WebMpa project how can I retrieve News with related picture.I define NewsViewModel in model folder and Map this ViewModel to NewsDto with Auto Mapper library.and in NewsController call NewsAppService and GetAll method for get news from database.I have 2 Scenario for this situation:
1- I think that change this method in .Application Project and add some linq query to get News with related Pictures from NewsAttachment
2- all operation about News and NewsAttachment and join with two entity stay in .WebMpa project and NewsController.
I confused really.would you help me with show example?

Cannot insert the value NULL into column from unrelated entity

I'm getting a "Cannot insert null into column" error from an unrelated table when trying to add a new record for the "original" table.
I have the following two (relevant) entities:
public class Complex
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public Guid OwnerId { get; set; }
[ForeignKey("OwnerId")]
public Owner Owner { get; set; }
public Guid AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
public virtual ICollection<Unit> Units { get; set; }
public virtual ICollection<StaffMember> StaffMembers { get; set; }
public Complex()
{
this.Id = System.Guid.NewGuid();
this.Units = new HashSet<Unit>();
this.StaffMembers = new HashSet<StaffMember>();
}
public void AddUnit(Unit unit)
{
Units.Add(unit);
}
public void AddStaff(StaffMember staffMember)
{
StaffMembers.Add(staffMember);
}
}
and
public class Owner
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public Guid ContactInfoId { get; set; }
[ForeignKey("ContactInfoId")]
public ContactInfo ContactInfo { get; set; }
public ICollection<StaffMember> Employees { get; set; }
public ICollection<Complex> Complexes { get; set; }
public Owner()
{
this.Id = System.Guid.NewGuid();
this.Employees = new HashSet<StaffMember>();
this.Complexes = new HashSet<Complex>();
}
public void AddEmployee(StaffMember employee)
{
Employees.Add(employee);
}
public void AddComplex(Complex complex)
{
Complexes.Add(complex);
}
}
I'm trying to add a new owner in the following code:
if (ModelState.IsValid)
{
Owner newOwner = new Owner();
ContactInfo newContactInfo = new ContactInfo();
Address newAddress = new Address();
newAddress.Address1 = viewModel.ContactInfo.Address.Address1;
newAddress.Address2 = viewModel.ContactInfo.Address.Address2;
newAddress.City = viewModel.ContactInfo.Address.City;
newAddress.State = viewModel.ContactInfo.Address.State;
newAddress.Zip = viewModel.ContactInfo.Address.Zip;
newContactInfo.Address = newAddress;
newContactInfo.Email = viewModel.ContactInfo.Email;
newContactInfo.Phone1 = viewModel.ContactInfo.Phone1;
newContactInfo.Phone2 = viewModel.ContactInfo.Phone2;
newOwner.Name = viewModel.Name;
newOwner.ContactInfo = newContactInfo;
using (REMSDAL dal = new REMSDAL())
{
dal.Owners.Add(newOwner);
var result = await dal.SaveChangesAsync();
if (result > 0)
{
viewModel.ActionStatusMessageViewModel.StatusMessage = "Owner " + viewModel.Name + " added.";
viewModel.Name = "";
return View(viewModel);
}
}
}
...but getting this error:
Exception Details: System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'OwnerId', table 'REMS.dbo.Complexes'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
How can I be getting an error regarding Complexes when I'm trying to add an Owner?

Update existing entity framework with database (by adding new tables from db)

Hi i have an entity and i am gonna add two tables from database named as country and state.
There is a relation between these two tables based on CountryId.
I used the "Update Model from database ..." to add these two entity types.
I have manually written two classes for these two entity-types given as below:-
public partial class Country
{
//[Key] //[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int CountryID { get; set; }
public string CountryName { get; set; }
}
public partial class State
{
public int StateID { get; set; }
public string StateName { get; set; }
public int CountryID { get; set; }
}
public DbSet<Country> Countries { get; set; }
public DbSet<State> States { get; set; }
Controller to fetch coutries and states :-
public JsonResult GetCountries()
{
List<Country> allCountry = new List<Country>();
using (SunilEntities dc = new SunilEntities())
{
allCountry = dc.Countries.OrderBy(a => a.CountryName).ToList();
}
return new JsonResult { Data = allCountry, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult GetStates(int countryID)
{
List<State> allState = new List<State>();
using (SunilEntities dc = new SunilEntities())
{
allState = dc.States.Where(a => a.CountryID.Equals(countryID)).OrderBy(a => a.StateName).ToList();
}
return new JsonResult { Data = allState, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
But I am getting an error "The entity type Country is not part of the model for the current context".
What should be the exact classes to be used to use these two tables in my controller?
Is there any way I can get automated classes after entity being updated with newer tables?
Under your yourmodel.edmx file there is yourmodel.tt and it generates relevant classes, thus there is no need to write these classes. By using relevant namespace you can use them.
I got the solution change models as below:-
public partial class Country
{
public Country()
{
this.States = new HashSet<State>();
}
public int CountryID { get; set; }
public string CountryName { get; set; }
public virtual ICollection<State> States { get; set; }
}
public partial class State
{
public int StateID { get; set; }
public string StateName { get; set; }
public Nullable<int> CountryID { get; set; }
public virtual Country Country { get; set; }
public virtual State State1 { get; set; }
public virtual State State2 { get; set; }
}
and change controller as given below:-
public JsonResult GetCountries()
{
using (SunilEntities dc = new SunilEntities())
{
var ret = dc.Countries.Select(x => new { x.CountryID, x.CountryName }).ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
// Fetch State by Country ID
public JsonResult GetStates(int countryID)
{
using (SunilEntities dc = new SunilEntities())
{
var ret = dc.States.Where(x => x.CountryID == countryID).Select(x => new { x.StateID, x.StateName }).ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}

MVC Code- or Model First

Most of the tutorials for MVC with Entity Framework are centered around Code-First, where you write classes for generating the model. This gives the advantage of control and Migrations, but I think it lack overview. I would therefore prefer to create the model using the graphical designer, but I cannot see how or if data migrations work in this context. It seems, that when I change the model (with data in the database), all the data is deleted in all tables.
Is there a way around this?
How can I do validation when using Model-First? Partial classes?
you may use the global validation beside mvc validation
example :
public class ValidationCriteria
{
public ValidType Type { get; set; }
public ValidRange Range { get; set; }
public ValidFormat Format { get; set; }
public ValidIsNull IsNull { get; set; }
public ValidCompare Compare { get; set; }
public ValidDB DB { get; set; }
public string Trigger { get; set; }
public Dictionary<string, ValidationCriteria> Before { get; set; }
public string After { get; set; }
public class ValidDB
{
public string functionName { get; set; }
public object[] param { get; set; }
public object functionClass { get; set; }
public string msg { get; set; }
public bool check = false;
}
public class ValidCompare
{
public string first { get; set; }
public string second { get; set; }
public string compareOperator { get; set; }
public string compareValue { get; set; }
public string msg { get; set; }
public bool check = false;
}
public ValidationCriteria()
{
this.Range = new ValidRange();
this.Format = new ValidFormat();
this.IsNull = new ValidIsNull();
this.Type = new ValidType();
this.Compare = new ValidCompare();
this.DB = new ValidDB();
this.Trigger = "blur";
this.Before = new Dictionary<string, ValidationCriteria>();
this.After = "";
}
public class ValidType
{
// checking element is integer.
public bool isInt { get; set; }
// checking element is decimal.
public bool isDecimal { get; set; }
public string msg { get; set; }
public bool check = false;
}
public class ValidRange
{
public long min { get; set; }
public long max { get; set; }
public string msg { get; set; }
public bool check = false;
}
public class ValidFormat
{
public bool isEmail { get; set; }
public string regex { get; set; }
public string msg { get; set; }
public bool check = false;
}
public class ValidIsNull
{
public string nullDefaultVal { get; set; }
public string msg { get; set; }
public bool check = false;
}
}
Meanwhile you may use validation part in your controller
Example :
private bool validateMaintainanceManagement(MaintainanceCRUD.Maintainance model, bool edit = false, bool ServerValidation = true)
{
bool ValidModel = false;
Dictionary<string, ValidationCriteria> validCriteria = new Dictionary<string, ValidationCriteria>();
#region maintainTitle Criteria
ValidationCriteria maintainTitle = new ValidationCriteria();
maintainTitle.IsNull.msg = Resources.Home.ErrmaintainTitle;
maintainTitle.IsNull.check = true;
maintainTitle.IsNull.nullDefaultVal = "-1";
//maintainTitle.Trigger = "change"; // this may trigger if you are using dropdown
validCriteria.Add("maintainTitle", maintainTitle);
#endregion

Saving Viewmodel data to the Database in ASP.NET MVC

I am new to ASP.net MVC and am using a viewmodel rather than viewbags to populate my dropdowns since I've seen most people recommend against them. I have a slick UI that does cascading dropdowns and autocompletes (not shown here) but I can't seem to get my data saved back to the database.
Models:
public partial class Car
{
public int CarID { get; set; }
public string CarName { get; set; }
public int ModelID { get; set; }
public int ManufacturerID { get; set; }
public int CarColorID { get; set; }
public Nullable<decimal> Price { get; set; }
public string Description { get; set; }
public virtual CarColor CarColor { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public virtual CarModel CarModel { get; set; }
}
public partial class CarColor
{
public CarColor()
{
this.Cars = new HashSet<Car>();
}
public int ColorID { get; set; }
public string ColorName { get; set; }
public virtual ICollection<Car> Cars { get; set; }
}
public partial class CarModel
{
public CarModel()
{
this.Cars = new HashSet<Car>();
}
public int CarModelID { get; set; }
public int ManufacturerID { get; set; }
public string CarModelName { get; set; }
public virtual ICollection<Car> Cars { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
}
public partial class Manufacturer
{
public Manufacturer()
{
this.Cars = new HashSet<Car>();
this.Manufacturer1 = new HashSet<Manufacturer>();
this.CarModels = new HashSet<CarModel>();
}
public int ManufacturerID { get; set; }
public string ManufacturerName { get; set; }
public Nullable<int> ParentID { get; set; }
public virtual ICollection<Car> Cars { get; set; }
public virtual ICollection<Manufacturer> Manufacturer1 { get; set; }
public virtual Manufacturer Manufacturer2 { get; set; }
public virtual ICollection<CarModel> CarModels { get; set; }
}
ViewModel:
public class AnotherTestViewModel
{
public Car car { get; set; }
public IEnumerable<SelectListItem> CarModels { get; set; }
public IEnumerable<SelectListItem> Manufacturers { get; set; }
public IEnumerable<SelectListItem> CarColors { get; set; }
}
Controller:
public ActionResult Create()
{
var model = new AnotherTestViewModel();
using (new CarTestEntities())
{
model.CarModels = db.CarModels.ToList().Select(x => new SelectListItem
{
Value = x.CarModelID.ToString(),
Text = x.CarModelName
});
model.Manufacturers = db.Manufacturers.ToList().Select(x => new SelectListItem
{
Value = x.ManufacturerID.ToString(),
Text = x.ManufacturerName
});
model.CarColors = db.CarColors.ToList().Select(x => new SelectListItem
{
Value = x.ColorID.ToString(),
Text = x.ColorName
});
}
return View(model);
}
//
// POST: /AnotherTest/Create
[HttpPost]
public ActionResult Create(AnotherTestViewModel model)
{
if (ModelState.IsValid)
{
db.Entry(model).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", "AnotherTestViewModel", new { id = model.car.CarID });
}
return View();
}
I saw a few recommendations to use Automapper because EntityState.Modified won't work, but I'm not sure how to configure it because using the code below didn't work.
Mapper.CreateMap<AnotherTestViewModel, Car>();
Mapper.CreateMap<Car, AnotherTestViewModel>();
var newCar = Mapper.Map<AnotherTestViewModel, Car>(model);
Any ideas?
Your view model should not be interacting with the database. View Models should only be used in the presentation layer (user interface) - hence the term "View" model. You should have another model (data model) that interacts with your database. Then you should have some type of service layer that handles your conversion between your view model and your data model (and vice versa). Your data model is the model generated by Entity Framework (which I assume is what you are using). To handle updates to your database, you need to instantiate a data context, grab the data entity from your database, make changes to that entity, and call save changes all in that data context. The data context will keep track of all changes to your entities and apply the necessary changes to your database when you call "save changes".
Example:
public void UpdateCar(CarViewModel viewModel)
{
using (DataContext context = new DataContext())
{
CarEntity dataModel = context.CarEntities.where(x => x.Id == viewModel.Id).First();
dataModel.Name = viewModel.Name;
dataModel.Type = viewModel.Type;
context.SaveChanges();
}
}
In this example, context will keep track of any changes to "dataModel". When "context.SaveChanges" is called, those changes will automatically be applied to the database.

Resources