InvalidOprerationException while trying to insert data into databse using entityframework MVC - c#

There are 2 tables in my database,
1. Employee, The model is below.
public class Employees
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DepartmentId { get; set; }
public string Designation { get; set; }
public DateTime DateOfBirth { get; set; }
[ForeignKey("Id")]
public virtual IList<Address> Address { get; set; }
}
I have another table named Address. The model is as below.
public class Address
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PinCode { get; set; }
}
An employee can have multiple address. I am dynamically adding controls for adding address. I am using Entityframe work for all the operations like creating DB, Updating etc.
The code I use for adding the data to database is as follows.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(string command,[Bind(Include = "Id,FirstName,LastName,DepartmentId,Designation,DateOfBirth")] Employees employees, [Bind(Include = "Id,AddressLine1,AddressLine2,City,State,PinCode")] List<Address> address)
{
if (ModelState.IsValid)
{
foreach (var item in address)
{
db.Address.Add(item);
}
db.Employees.Add(employees);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employees);
}
When I insert data, the data is getting inserted in the database but I am getting the following exception.
An exception of type 'System.InvalidOperationException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: Unable to set field/property Address on entity type GridSample.Models.Employees. See InnerException for details.
The Innerexception :
{"Unable to cast object of type 'GridSample.Models.Address' to type 'System.Collections.Generic.IList`1[GridSample.Models.Address]'."}
Please help me to sort out this issue.

I think you cannot use ForeignKeyAttribute on a property in the "one" class in one-to-many relation. It should be used on a property in the "many" class to specify the key of the "one" class instance. So, in your case, you should modify your entity classes to reflect the relationship.
public class Employees
{
//...
[InverseProperty("Employee")]
public virtual ICollection<Address> Addresses { get; set; }
}
public class Address
{
//...
public int EmployeeId { get; set; }
[ForeignKey("EmployeeId"), InverseProperty("Addresses")]
public virtual Employees Employee { get; set; }
}
Here the ForeignKeyAttribute is used to decorate the navigation property and specify the key property. Otherwise, you can decorate the key property and specify the navigation property, like so:
public class Address
{
//...
[ForeignKey("Employee")]
public int EmployeeId { get; set; }
[InverseProperty("Addresses")]
public virtual Employee Employee { get; set; }
}
EDIT
The reason you're not getting any addresses is because you're adding employee and addresses to the database independently, i.e. without indicating the relation between them. There are several ways to do that, and I think the simplest is to make use of the navigation properties:
Either I: Add the addresses to the employee's address collection rather than directly to a dbset:
foreach (var item in address)
{
employees.Addresses.Add(item);
}
db.Employees.Add(employees);
db.SaveChanges();
Or II: For each address specify the employee to whom it belongs:
foreach (var item in address)
{
item.Employee = employees;
db.Address.Add(item);
}
db.Employees.Add(employees);
db.SaveChanges();

Related

Get data from relational tables using entity framework C# WebApi

I am using Webapi and i have two tables in database and Department and Info tables. Department table has relation with Info table. I am using entity framework to retrieve data from database but I am getting data from only one table INFO so the department table shows NULL it has to show department data because both have relation.
Without Webapi the code is working fine. So where I am wrong and why does not Department table show in webapi.
I hope you understand my question thanks.
Contorller
public class WebApiController : ApiController
{
[HttpGet]
public IHttpActionResult EmployeeList()
{
var List = DB.Infoes.ToList().OrderByDescending(x => x.ID);
return Json(List);
}
}
Model
public partial class Info
{
public int ID { get; set; }
public string Image_Name { get; set; }
public string First_Name { get; set; }
public string Last_name { get; set; }
public string Desription { get; set; }
public Nullable<int> DeprtmentIDFK { get; set; }
public virtual Department Department { get; set; }
}
public partial class Department
{
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
public virtual ICollection<Info> Infoes { get; set; }
}
As it is discussed here, in order to fetch navigation properties you have to Include them in your IQueryable, otherwise you always get null values.

How to add a entity to collection inside another entity in Entity Framework asp.net mvc

I have two entities (student, yogaspaceevent). Yogaspaceevent which is like a exercise class, has a collection of students as RegisteredStudents and I want to be able to add students to this event to register them.
I tried a couple of things but can't seem to add a student to a yogaspaceevent, so maybe I'm not doing it correctly.
Question: do I need to create a whole new entity (say registeredstudents) to add students to a yogaspaceevent? Because I thought Entity Framework would somehow create this table for me or do some other magic under the hood to add a student to a event? The only solution I have is to create a RegisteredStudent entity and then EF will create a table. Is this the right solution?
Here are my two entities:
public class YogaSpaceEvent
{
public int YogaSpaceEventId { get; set; }
[Index]
public DateTime DateTimeScheduled { get; set; }
public int AppointmentLength { get; set; }
public int StatusEnum { get; set; }
public virtual ICollection<Student.Student> RegisteredStudents { get; set; }
[Index]
public int YogaSpaceRefId { get; set; }
[ForeignKey("YogaSpaceRefId")]
public virtual YogaSpace YogaSpace { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public virtual StudentImage StudentImage { get; set; } //one-to-one
[MaxLength(50)]
public string CatchPhrase { get; set; }
[MaxLength(250)]
public string Education { get; set; } //Serra High School, San Diego State Univesity
public string Work { get; set; } // Taco Bell, Starbucks
[MaxLength(250)]
public string WhyIPractice { get; set; }
public StudentStatus Status { get; set; }
}
Here is my controller where I want to add a student to an event but I get exceptions thrown.
[HttpPost]
public ActionResult RegisterStudentForEvent(int eventId)
{
try
{
Student student = _studentRepository.Find(User.Identity.GetUserId()); //User.Identity.GetUserId()
if (student == null)
{
return Json( new { error = "notification", message = "You need an active student profile to register, please complete your student profile." });
}
var spaceEvent = _yogaSpaceEventRepository.Find(eventId);
if (spaceEvent.RegisteredStudents == null)
{
spaceEvent.RegisteredStudents = new Collection<Student>(); // new EntityCollection<Student>(); neither of these two work, both throw exceptions
}
spaceEvent.RegisteredStudents.Add(student);
_yogaSpaceEventRepository.Modify(spaceEvent);
_yogaSpaceEventRepository.Save();
// send email confirmation with a cancel link in it.
return Json(new { error = "false", message = "Now registered!. A confirmation email has been sent. Have fun! " });
}
catch (Exception ex)
{
return Json( new { error = "true", message = ex.Message });
}
}
Here are the two exceptions that are thrown when I try both methods above.
The object could not be added to the EntityCollection or EntityReference. An object that is attached to an ObjectContext cannot be added to an EntityCollection or EntityReference that is not associated with a source object.
and
The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
I was having similar issue.
Your above code seems to be correct , I think you have missed to specify the mapping in dbcontext.cs class which resulted in below error:
The object could not be added to the EntityCollection or
EntityReference. An object that is attached to an ObjectContext cannot
be added to an EntityCollection or EntityReference that is not
associated with a source object.
I hope my below example could help you.
Specialization (Parent Entity Class)
[Table("M_Specialization")]
public partial class Specialization : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int SID { get; set; }
public string SCode { get; set; }
public string Description { get; set; }
public virtual ICollection<SubSpecialization> SubSpecializationDetails { get; set; }
}
Sub specialization (Child Entity Class)
[Table("M_SubSpecialization")]
public partial class SubSpecialization : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Int32 SuID { get; set; }
public string SubCode { get; set; }
public Int32 SID { get; set; } // This is required in order to map between specialization and subspecialization
[ForeignKey("SID")]
public virtual Specialization Specialization { get; set; }
}
dbcontext.cs:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<SubSpecialization>().HasRequired(c => c.Specialization)
.WithMany(s => s.SubSpecializationDetails)
.HasForeignKey(c => c.SID);
}
You need to define a many-to-many relationship between Student and YogaSpaceEvent. The code you have created so far represents a one-to-many relationship.
An description of how to do that can be found here and here
What you need to add to your code is:
- Add a ICollection property to your Student class
- In your dbcontext.OnModelCreating, add code to define the many-to-many relationship.
As far as I can see, your controller function is OK.

Unable to determine the principal end of an association - Entity Framework Model First

I have created Entity Data Model in Visual Studio. Now I have file with SQL queries and C# classes generated from Model.
Question:
Classes are generated without annotations or code behind (Fluent API). Is it OK? I tried to run my application but exception was thrown:
Unable to determine the principal end of an association between the types 'Runnection.Models.Address' and 'Runnection.Models.User'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I read that I can not use Fluent API with "Model First". So what can I do?
Code:
User
public partial class User
{
public User()
{
this.Events = new HashSet<Event>();
this.CreatedEvents = new HashSet<Event>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Photo { get; set; }
public int EventId { get; set; }
public string Nickname { get; set; }
public OwnerType OwnerType { get; set; }
public NetworkPlaceType PlaceType { get; set; }
public virtual ICollection<Event> Events { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Event> CreatedEvents { get; set; }
public virtual Owner Owner { get; set; }
}
Address
public partial class Address
{
public int Id { get; set; }
public string Street { get; set; }
public string StreetNumber { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
public virtual User User { get; set; }
}
Context
//Model First does not use this method
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Address>().HasRequired(address => address.User)
.WithRequiredDependent();
modelBuilder.Entity<User>().HasRequired(user => user.Address)
.WithRequiredPrincipal();
base.OnModelCreating(modelBuilder);
}
You have to specify the principal in a one-to-one relationship.
public partial class Address
{
[Key, ForeignKey("User")]
public int Id { get; set; }
public string Street { get; set; }
public string StreetNumber { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
public virtual User User { get; set; }
}
By specifying a FK constraint, EF knows the User must exists first (the principal) and the Address follows.
Further reading at MSDN.
Also, see this SO answer.
Updated from comments
In the designer, select the association (line between Users & Address). On the properties window, hit the button with the [...] on Referential Constraint (or double click the line). Set the Principal as User.
Error:
Had same error of "Unable to determine the principal end of an association between the types 'Providence.Common.Data.Batch' and 'Providence.Common.Data.Batch'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.".
HOWEVER, note that this is the SAME table.
Cause: My database was MS SQL Server. Unfortunately when MS SQL Server's Management Studio adds foreign keys, it adds the default foreign key as Batch ID column of Batch table linking back to itself. You as developer are suppose to pick another table and id to truly foreign key to, but if you fail to it will still allow entry of the self referencing FK.
Solution:
Solution was to delete the default FK.
Cause 2: Another situation is that the current table may be fixed but the old historical image of the table when the EF's edmx was done had the default FK.
Solution 2: is to delete the table from the Model Browser's Entity Types list and click "yes" and then "Update Model from the Database" again.

Entity Framework 5 complex type and unknown column in field list error

Bear with me as I'm new to C# and programming in general.
I'm trying to define a complex type that is in the same table as the principle class. Basically, it's the good old User and Address example.
public class Customer
{
[Key]
public int customerId { get; set; }
//some attributes
public string street { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string postal { get; set; }
}
So I try to slice off the address information into its own class:
public class Customer
{
[Key]
public int customerId { get; set; }
//some attributes
public Address address { get; set; }
}
[ComplexType]
public class Address
{
public string street { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string postal { get; set; }
}
I get no compile error and when I load a view that access the Customer model, I get an unknown column in field set error.
Unknown column 'Extent1.address_street' in 'field list'
I basically followed this example: http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx
Is there something I"m missing or something different with EF5?
By default EF expects columns for properties of complex types in form {complextypename_propertyname}. If you created your tables manually and named columns differently there will be a mismatch. Can you try renaming the columns accordingly (i.e. street to address_street) and try if it works. Alternatively you should be able to add an attribute to the properties on the complex type to tell EF that is should not use the convention but the name you specified (e.g. [Column("street")] for the street property).

Entity Framework 4.1 RC (Code First) - Entity not updating over association

What I'm trying to do is fairly simple. I have two classes:
public class TownRecord
{
public int Id { get; set; }
public string ShortName { get; set; }
public string FileName { get; set; }
public string tags { get; set; }
public virtual TownRecordType RecordType { get; set; }
public DateTime? DateScanned { get; set; }
public DateTime? RecordDate { get; set; }
[StringLength(4000)]
public string Comments { get; set; }
public string UploadedBy { get; set; }
}
public class TownRecordType
{
public int Id { get; set; }
public string RecordType { get; set; }
public virtual ICollection<TownRecord> TownRecords {get; set; }
}
When I want to update the RecordType property on the TownRecord class, I find that the association fails to update. No exception is thrown but the update is not performed:
[HttpPost]
public ActionResult Edit(int id, TownRecord tr, FormCollection collection)
{
TownRecordType newRecType = _ctx.TownRecordTypes.Find(Int32.Parse(collection["RecordType"]));
tr.RecordType = newRecType;
_ctx.Entry(tr).State = EntityState.Modified;
_ctx.SaveChanges();
return RedirectToAction("List");
}
NOTE: I removed my error handling for clarity...
I've seen a question similar to this here but I'm not getting it. This is probably a really foolish rookie mistake but I've StackOverflowing and Googling for several hours and getting nowhere. Any help is greatly appreciated.
This doesn't work because you are using independent association. Relation between TownRecord and TownRecordType is not part of town record's entry so changing state to modified doesn't say anything about state of relation. That is the real meaning of "independent" - it has its own entry but for unknown reason it is hard to get it in DbContext API (EF 4.1). Proposed way is using Foreign key association instead of independent association. To change your association to foreign key you must do this:
public class TownRecord
{
public int Id { get; set; }
...
[ForeignKey("RecordType")]
public int RecordTypeId { get; set; }
public virtual TownRecordType RecordType { get; set; }
...
}
You will change your code to:
[HttpPost]
public ActionResult Edit(int id, TownRecord tr, FormCollection collection)
{
tr.RecordTypeId = Int32.Parse(collection["RecordType"]);
_ctx.TownRecords.Attach(tr);
_ctx.Entry(tr).State = EntityState.Modified;
_ctx.SaveChanges();
return RedirectToAction("List");
}
Actually the question with the same problem was asked 2 hours before you asked the question. I also tried to provide solution which works with independent association but I don't like it. The problem is that for independent association you need to have attached TownRecord loaded its actual TownRecordType and replace it with new TownRecordType.

Categories

Resources