TryUpdateModel Error - asp.net-mvc-3

First time I can add Allergies into my DB without a problem is As below screen.
But when I try to add 2nd record (after save the first record) then it gives below mentioned run time exception (is as below screen).
Run time Exception
An error occurred while saving entities that do not expose foreign key
properties for their relationships. The EntityEntries property will
return null because a single entity cannot be identified as the source
of the exception. Handling of exceptions while saving can be made
easier by exposing foreign key properties in your entity types. See
the InnerException for details.
Stack Trace (this is for when I try to add 2nd record for medical table.But it is same for Allergies Table also)
Violation of PRIMARY KEY constraint 'PK__Medicati__3214EC0768A0EA12'.
Cannot insert duplicate key in object 'dbo.Medications'. The statement
has been terminated.
Action Method
[HttpPost]
public ActionResult EditMedicalInfo(string providerKey, string ownerKey, string petKey)
{
var pet = Repository.GetPet(ownerKey, petKey);
if (TryUpdateModel(pet))
{
Repository.Save();
}
var url = Url.AbsoluteRouteUrl("PetDetail", new { controller = "customers", action = "detail", providerKey = providerKey, ownerKey = ownerKey, petKey = petKey }) + "#medical";
return Redirect(url);
}
Pet Model
public class Pet {
public Pet() { Id = Guid.NewGuid(); Created = DateTime.Now; }
public Guid Id { get; set; }
public virtual Owner Owner { get; set; }
[StringLength(50), Required]
public string Name { get; set; }
public string Key { get; set; }
public DateTime Created { get; set; }
[Display(Name = "Birth Date"), DataType(DataType.Date)]
public DateTime? BirthDate { get; set; }
[EnumDataType(typeof(PetType)), UIHint("EnumerationList")]
[Required]
public int Type { get; set; }
[Required]
public Guid BreedId { get; set; }
[Display(Name = "Breed"), ForeignKey("BreedId")]
public virtual Breed Breed { get; set; }
[EnumDataType(typeof(Gender)), UIHint("EnumerationList")]
[Required]
public int? Gender { get; set; }
public double Weight { get; set; }
[Display(Name = "License #")]
public string LicenseNumber { get; set; }
[Display(Name = "Microchip #")]
public string MicrochipNumber { get; set; }
public int? AgeValue { get { return (BirthDate.HasValue) ? (int)(DateTime.Today - BirthDate.Value).TotalDays : default(int?); } }
public string Age { get { return (BirthDate.HasValue) ? BirthDate.Value.ToAge() : "Unknown"; } }
public virtual ICollection<PetPhoto> Photos { get; set; }
public virtual ICollection<Appointment> Appointments { get; set; }
public virtual ICollection<MedicalRecordOrder> Orders { get; set; }
public virtual ICollection<PetDocument> Documents { get; set; }
public virtual ICollection<PetNote> Notes { get; set; }
public virtual ICollection<PetProvider> Providers { get; set; }
public virtual ICollection<PetService> PetServices { get; set; }
public Guid? Avatar { get; set; }
public virtual MedicalRecord Medical { get; set; }
public virtual BehavioralRecord Behavioral { get; set; }
public virtual DietRecord Diet { get; set; }
public Guid? EmergencyVeterinarianId { get; set; }
[ForeignKey("EmergencyVeterinarianId")]
public virtual Provider EmergencyVeterinarian { get; set; }
public virtual ICollection<PetContact> Contacts { get; set; }
[EnumDataType(typeof(ProfileCreatorType))]
public int ProfileCreator { get; set; }
[EnumDataType(typeof(PetClassification)), UIHint("EnumerationList")]
public int Classification { get; set; }
[UIHint("InsuranceCarrier")]
public virtual string InsuranceCarrier { get; set; }
// Non persisted extensions
/// <summary>
/// Non Persisted
/// </summary>
[NotMapped]
public List<AppointmentInfo> AppointmentInfos { get; set; }
/// <summary>
/// Non Persisted
/// </summary>
[NotMapped]
public List<AppointmentInfo> SiblingAppointmentInfos { get; set; }
public IList<ReservationRequest> ReservationRequests { get; set; }
[UIHint("QuickList")]
public virtual ICollection<SpecialInstruction> SpecialInstructions { get; set; }
public virtual PetSitterRestrictionPermission PetSitterRestrictionPermission { get; set; }
public virtual PetSitterBehavior PetSitterBehavior { get; set; }
public virtual PetSitterCleaningRecord PetSitterCleaningRecord { get; set; }
public virtual PetSitterNote PetSitterNote { get; set; }
}
Allergy Model
public class Allergy {
public Allergy() { Id = Guid.NewGuid(); }
[ScaffoldColumn(false)]
public Guid Id { get; set; }
public string Name { get; set; }
public string Treatment { get; set; }
}
How could I avoid above error when I try to add 2nd record ?

Related

Why is Entity Framework navigation property null?

I am use code first model with a relationship below
public class ApplicationUser : IdentityUser
{
public string UserFirstName { get; set; }
public string UserLastName { get; set; }
public string UserSchool { get; set; }
public UserProfileData UserProfileData { get; set; }
public int? MedicalSpecialtyId { get; set; }
public virtual MedicalSpecialty MedicalSpecialty { get; set; }
// public int? AnalyticsDataId { get; set; }
// public ICollection<AnalyticsData> AnalyticsDatas { get; set; }
}
public class MedicalSpecialty
{
public int Id { get; set; }
public string Description { get; set; }
// public int ApplicationUserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
public ICollection<ProgramDetailData> ProgramDetailDatas { get; set; }
}
And when I try to get a User's associated MedicalSpecialty object it is NULL
userSpecialtyName = currentUser.MedicalSpecialty.Description;
BUT when I run this code above it the currentUser.MedicalSpecialty is no longer NULL. What happened?? Somehow that LINQ query woke up the object and filled it with data
var userSpecialtyId = currentUser.MedicalSpecialtyId;
userSpecialtyName = _medicalSpecialtyRepository.Find
(x => x.Id == userSpecialtyId).FirstOrDefault().Description;
userSpecialtyName = currentUser.MedicalSpecialty.Description;

Entity Framework not binding entity

I have the following db structure:
I am using EF6 to create the entities from database and have the following classes created by EF6:
public partial class Mechanic
{
public Mechanic()
{
this.MechanicAddresses = new HashSet<MechanicAddress>();
this.MechanicServices = new HashSet<MechanicService>();
}
public string ID { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string MobileNumber { get; set; }
public Nullable<bool> IsMobile { get; set; }
public string Url { get; set; }
public string FaceBookUrl { get; set; }
public string TwitterUrl { get; set; }
public string Description { get; set; }
public string Discriminator { get; set; }
public bool IsEnabled { get; set; }
public bool IsAuthorised { get; set; }
public string Logo { get; set; }
public System.DateTime CreationTimestamp { get; set; }
public virtual ICollection<MechanicAddress> MechanicAddresses { get; set; }
public virtual ICollection<MechanicService> MechanicServices { get; set; }
}
public partial class MechanicAddress
{
public int ID { get; set; }
public string MechanicId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string District { get; set; }
public string Region { get; set; }
public string PostalCode { get; set; }
public int CountryId { get; set; }
public System.DateTime CreationTimestamp { get; set; }
public bool IsPrimary { get; set; }
public Nullable<double> Latitude { get; set; }
public Nullable<double> Longitude { get; set; }
public System.Data.Entity.Spatial.DbGeography Location { get; set; }
public virtual Country Country { get; set; }
public virtual Mechanic Mechanic { get; set; }
}
public partial class MechanicService
{
public int ID { get; set; }
public string MechanicId { get; set; }
public string Service { get; set; }
public virtual Mechanic Mechanic { get; set; }
}
The data is correct so i expect to get data in all entities.
When i run the following linq query in my DAL:
Mechanic mech = context.Mechanics.Where(a => a.ID == id).Include(a => a.MechanicAddresses).Include(a => a.MechanicServices).FirstOrDefault();
It returns the mechanic and mechanicAddresses but mechanicServices is always empty (count == 0).
When i run the same query in LinqPad I get all entities filled as expected.
I have removed the edmx and re-created it but still get the same issue.
Please check if "MultipleActiveResultSets" is set to true and LazyLoadingEnabled is enabled in connection string. It may help.
And what about your OnModelCreating?
protected override void OnModelCreating(DbModelBuilder modelBuilder)
It's not necessary to use Include if you have LazyLoading (virtual). And If it works fine in LinqPad try to do migration into empty DB (just test). And then try to get data from test DB.
The only way i was able to resolve this was to:
delete the EDMX
script the create for the mechanicsServices table
script the data
drop the mechanicsServices table
run the create table script from above
run the insert data script
regenerate the EDMX
This now works, WTF! Can't explain it.
I know it's always best to understand what went wrong but this one beat me.
I had same problem.
If you using git, please check .edmx file old version. SSDL content may be missing.

Relationships between tables mvc3

I'm building website in MVC 3.
i am using EF code first in existing database.
my ET inside the model look like that:
public class Pages
{
[Required]
public int ID { get; set; }
public int ParentID { get; set; }
[Required]
public int PageType { get; set; }
[Required]
[DataType(DataType.Text)]
[DisplayName("כותרת")]
public string Title { get; set; }
public string SearchWords { get; set; }
public string Leng { get; set; }
public int? Sort { get; set; }
public string Modules { get; set; }
[ForeignKey("PageType")]
public virtual PagesType Type { get; set; }
public virtual IEnumerable<PagesType> Types { get; set; }
[ForeignKey("PageID")]
public ICollection<PageContent> PageContent { get; set; }
[ForeignKey("PageID")]
public virtual ICollection<ImagesTable> Images { get; set; }
}
public class PageContent
{
public int ID { get; set; }
public int PageID { get; set; }
public string Header { get; set; }
public string Text { get; set; }
[ForeignKey("ID")]
public virtual ICollection<Pages> Pages { get; set; }
}
as you see in my fist table that cold Pages i have a relationship to another table that named PageContent.
in my Pages class i had this code
[ForeignKey("PageID")]
public ICollection<PageContent> PageContent { get; set; }
now, when i trying to add new pageContent into new page i get an error.
see this code
public ActionResult AddPage(PageModel page)
{
SystemLogic cmd = new SystemLogic();
page.Leng = "he";
Models.Pages p = new Pages();
p.ParentID = page.ParentID;
PageContent pageContent = new PageContent();
pageContent.Text = page.Content;
p.PageContent.Add(pageContent);
The error is
Object reference not set to an instance of an object.
What i did wrong?
You will get the NRE at p.PageContent.Add(pageContent); because the collection is not initialized. Initialize the collections inside the constructor of Pages class.
public class Pages
{
public Pages()
{
PageContent = List<PageContent>();
Images = List<ImagesTable>();
}
[Required]
public int ID { get; set; }
public int ParentID { get; set; }
[Required]
public int PageType { get; set; }
[Required]
[DataType(DataType.Text)]
[DisplayName("כותרת")]
public string Title { get; set; }
public string SearchWords { get; set; }
public string Leng { get; set; }
public int? Sort { get; set; }
public string Modules { get; set; }
[ForeignKey("PageType")]
public virtual PagesType Type { get; set; }
public virtual IEnumerable<PagesType> Types { get; set; }
[ForeignKey("PageID")]
public ICollection<PageContent> PageContent { get; set; }
[ForeignKey("PageID")]
public virtual ICollection<ImagesTable> Images { get; set; }
}
Or before you add objects to the collection
if (p.PageContent == null) p.PageContent = new List<PageContent>();
p.PageContent.Add(pageContent);
You should consider using proper naming conventions(eg Page instead of Pages).

Entity Framework also Linq advice needed

i have got on my DB 3 tables
movies, workers, workermovies ( this is the Relationship table )
public class Movie
{
public Movie()
{
Genres = new List<Genre>();
Formats = new List<Format>();
ProductionCompanies = new List<ProductionCompany>();
Workers = new List<Worker>();
}
public int Id { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string StoryLine { get; set; }
public int RunTime { get; set; }
[ForeignKey("MPAARateId")]
public MPAARate MPAARate { get; set; }
public int MPAARateId { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
public DateTime CreatedDate { get; set; }
public string OfficialSite { get; set; }
public int Budget { get; set; }
public int StatusId { get; set; }
public virtual ICollection<Genre> Genres { get; set; }
public virtual ICollection<Format> Formats { get; set; }
public virtual ICollection<ProductionCompany> ProductionCompanies { get; set; }
public virtual ICollection<Worker> Workers { get; set; }
}
public class Worker
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime Birthday { get; set; }
public string Biography { get; set; }
public string BornName { get; set; }
public double Height { get; set; }
public DateTime? Died { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
public bool IsActor { get; set; }
public bool IsDirector { get; set; }
public bool IsWriter { get; set; }
public bool IsProducer { get; set; }
public bool IsStar { get; set; }
public virtual ICollection<Movie> Movies { get; set; }
}
in this Relation i got the movieId and the workerId
but i also got some more fields if the person acted or writen or producer etc.
how do i define the relation entity class if needed
and when i want to get just the ppl that acted in the movie how do i wrote such a linq
query
You need to introduce an additional entity in your model WorkerMovie and convert the many-to-many relationship between Worker and Movie into two one-to-many relationships - one between Worker and WorkerMovie and the other between Movie and WorkerMovie. A sketch:
public class WorkerMovie
{
[Key, Column(Order = 0)]
public int WorkerId { get; set; }
[Key, Column(Order = 1)]
public int MovieId { get; set; }
public Worker Worker { get; set; }
public Movie Movie { get; set; }
public bool WorkedAsActor { get; set; }
public bool WorkedAsWriter { get; set; }
public bool WorkedAsProducer { get; set; }
// etc.
}
public class Movie
{
// ...
public virtual ICollection<WorkerMovie> WorkerMovies { get; set; }
// remove ICollection<Worker> Workers
}
public class Worker
{
// ...
public virtual ICollection<WorkerMovie> WorkerMovies { get; set; }
// remove ICollection<Movie> Movies
}
If you want only to find the workers who were actors in a particular movie with a movieId you can write:
var workersAsActors = context.WorkerMovies
.Where(wm => wm.MovieId == movieId && wm.WorkedAsActor)
.Select(wm => wm.Worker)
.ToList();
Here is another answer to a very similar question with many more examples of possible queries: Create code first, many to many, with additional fields in association table

EF 4.1 - Model Relationships

I'm trying to create a quick ASP.NET MVC 3 application using the RC version of EF 4.1. I have two models:
public class Race
{
public int RaceId { get; set; }
public string RaceName { get; set; }
public string RaceDescription { get; set; }
public DateTime? RaceDate { get; set; }
public decimal? Budget { get; set; }
public Guid? UserId { get; set; }
public int? AddressId { get; set; }
public virtual Address Address { get; set; }
}
and
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string StreetCont { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public virtual Race Race { get; set; }
}
I get the following error when trying to insert a new Race:
Unable to determine the principal end
of an association between the types
'rcommander.Models.Race' and
'rcommander.Models.Address'. The
principal end of this association must
be explicitly configured using either
the relationship fluent API or data
annotations.
Shouldn't it recognize RaceId as the primary key of the Races table and AddressId as the FK to the Addresses table automatically? Am I missing something?
Thanks!
The problem here seems to be that EntityFramework can't recognize where the foreing key is, as you are holding cross references in both objects. Not being sure what you want to achieve, I may suggest something like this:
public class Race
{
public int RaceId { get; set; }
public string RaceName { get; set; }
public string RaceDescription { get; set; }
public DateTime? RaceDate { get; set; }
public decimal? Budget { get; set; }
public Guid? UserId { get; set; }
public int? AddressId { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string StreetCont { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
Skipping reference to Race in second entity.
The problem here is 1:1 relation between Address and Race! You probably want to map it as 1:N so you need to modify address to:
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string StreetCont { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public virtual ICollection<Race> Races { ... }
}
If you want to use 1:1 then you can't use AddressId in Race but AddressId in Address must be foreign key of Race because entity framework can achive 1:1 only be "sharing" primary key.
For one-to-one relationship, you need to add "[required]" attribute in the second class. See below:
public class Race
{
public int RaceId { get; set; }
public string RaceName { get; set; }
public string RaceDescription { get; set; }
public DateTime? RaceDate { get; set; }
public decimal? Budget { get; set; }
public Guid? UserId { get; set; }
public int? AddressId { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string StreetCont { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
[required]
public Race Race { get; set; }
}
There is a good post: Associations in EF Code First CTP5: Part 2 – Shared Primary Key Associations
http://weblogs.asp.net/manavi/archive/2010/12/19/entity-association-mapping-with-code-first-one-to-one-shared-primary-key-associations.aspx
It recognizes Id as the primary key by convention. So what you need to do:
public class Race
{
[Key]
public int RaceId { get; set; }
public string RaceName { get; set; }
public string RaceDescription { get; set; }
public DateTime? RaceDate { get; set; }
public decimal? Budget { get; set; }
public Guid? UserId { get; set; }
public int? AddressId { get; set; }
public virtual Address Address { get; set; }
}
and
public class Address
{
[Key]
public int AddressId { get; set; }
public string Street { get; set; }
public string StreetCont { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
[ForeignKey("RaceId")] // Maybe telling it what the ForeignKey is will help?
public virtual Race Race { get; set; }
}
The [Key] attribute indicates that it should be the PrimaryKey
If you don't want this, you need to rename your primary keys to simply public int Id {get; set; }
I think it would be solved also like this... I assumed that an address is not required to be associated with a race, but a race must always be associated with an address.
I had the same problem with Patients and Incidents and i solved it with InverseProperty which is actually the same with foreign key, but the other direction
public class Race
{
public int RaceId { get; set; }
public string RaceName { get; set; }
public string RaceDescription { get; set; }
public DateTime? RaceDate { get; set; }
public decimal? Budget { get; set; }
public Guid? UserId { get; set; }
public int AddressId { get; set; }
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string StreetCont { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public int? RaceId { get; set; }
[InverseProperty("RaceId")]
public Race Race { get; set; }
}

Resources