Error adding entities to database - c#

I'm getting the following exception message:
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.
And my inner exception is related to me change column names on my table as they didn't make sense before (They were given the name Customer_Customer_ID) and renamed my Sku and my Customer objects that are composed in my cart, with the following data annotations
[Table("Cart")]
public class Cart
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public Guid CartID { get; set; }
[Column("SkuID")]
public virtual Sku Sku { get; set; }
[Required]
public int Quantity { get; set; }
[Column("CustomerID")]
public virtual Customer Customer { get; set; }
public bool IsCheckedOut { get; set; }
}
This is the inner exception of the exception message
"Invalid column name 'Customer_Customer_ID'.\r\nInvalid column name
'Sku_SKU_ID'."
What is the correct way to name these composed objects and do I need to modify my OnModelCreating to reflect these changes to entity framework?

Add a SkuID and CustomerId property to your entity class.
public class Cart
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public Guid CartID { get; set; }
public int SkuID { set;get;}
public virtual Sku Sku { get; set; }
[Required]
public int Quantity { get; set; }
public int CustomerID{ set;get;}
public virtual Customer Customer { get; set; }
public bool IsCheckedOut { get; set; }
}
Assuming your Sku and Customer class has an ID property of type int and it is the primary key. EF will create Cart table with foreign keys to Sku and Customer table(s) properly because the current structure follow the convention.
Now your entity class has both integer Id (CustomerID) and the navigation property (Customer)

Related

How to update foreign key in EF 6 - Code First - One to many relationship

Based on the solution provided in this question : How to update foreign key in EF 6 - Code First, I'm able to update my foreign key using the id field.
But now, I get an exception when getting entities from the database. Using this code :
// Retrieve data first
using (var db = new TestDbContext())
{
var p2 = db.Persons.First();
}
I get the following SqlException : "Invalid column name 'Country_Id1'."
Does anyone have any clues to be able to retrieve data and to update the foreign key ?
Asked in another way, is it possible to use both the navigation property to ease the use of my entity and the id of the foreign key to be able to update my dependent entity ?
My entities
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Country Country { get; set; }
public int Country_Id { get; set; }
}
public class Country
{
public int Id { get; set; }
public string Name { get; set; }
}
That might be because entity framework is trying to create new foreign key based on navigation property Country in Person entity.
I think you should annotate Country_Id property with ForeignKey attribute as below.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Country_Id")]
public virtual Country Country { get; set; }
public int Country_Id { get; set; }
}
However if you follow the ef naming convention for naming property as below, you don't need to annotate it.
Any property with the same data type as the principal primary key
property and with a name that follows one of the following formats
represents a foreign key for the relationship: '', '', or ''
You may read more from here
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Country Country { get; set; }
public int CountryId { get; set; }
}
Note: you might need to run database migration or need to recreate database.

ASP.NET MVC EF Migration Foreign Key error

I have two classes that have a 1 to many relationship which are Format class and Exam class. Thus, I use the Code First Migrations to add the navigation properties for each classes as well as a Foreign Key property. However, when I enter the command update-database, it presents me with this error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Exams_dbo.ExamFormats_ExamFormatID". The conflict occurred in database "aspnet-ExamBankSys-20161202012850", table "dbo.ExamFormats", column 'id'.
Format Model
public class ExamFormat
{
[Key]
public int id { get; set; }
public string FormatDesc { get; set; }
public virtual ICollection<Exam> Exams { get; set; }
}
Exam Model
public class Exam
{
[Key]
public int id { get; set; }
[DataType(DataType.Date)]
public DateTime ExamDate { get; set; }
public int ModuleId { get; set; }
public virtual Module Module { get; set; }
[ForeignKey("ExamFormat")]
public int ExamFormatID { get; set; }
public virtual ExamFormat ExamFormat { get; set; }
}
It works for the public int ModuleId with the navigation property of Module. However, the migration does not work for the class ExamFormat even when I specify the [ForeignKey] annotation. Any idea how to solve this?

Code First Optional One-To-One Relationship

Writing a model for situation where I have two tables which are customers and users. Each user record might have an optional related customer record and vice versa, but none of them is a must. I figured out that FK Associations are not what I need, but Independent Associations are. But I just can find a way to make it work, I keep getting the 'Unable to determine the principal end...The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.' exception.
My models are very simple:
public class User
{
[Key]
public int Id { get; set; }
[StringLength(20)]
public string CustomerId { get; set; }
public string Password { get; set; }
public bool Locked { get; set; }
//[ForeignKey("CustomerId")]
public virtual Customer Customer { get; set; }
}
public class Customer
{
[Key]
[Column("Id", TypeName = "nvarchar")]
[StringLength(20)]
public string Id { get; set; } // nvarchar 20
[Required]
public string GivenName { get; set; } // nvarchar 100
[Required]
public string Surname { get; set; } // nvarchar 100
//[InverseProperty("Customer")]
public virtual User User { get; set; }
}
I've tried to add the ForeignKeyAttribute and InversePropertyAttribute, which are currently commented out, but they didn't help either. I would prefer to use data annotations and not fluent API, if it's possible in my case.
In one-to-one relation one end must be principal and second end must be dependent. Principal end is the one which will be inserted first and which can exist without the dependent one. Dependent end is the one which must be inserted after the principal because it has foreign key to the principal. When configuring one-to-one relationships, Entity Framework requires that the primary key of the dependent also be the foreign key.This problem is most easily solved by using a ForeignKey annotation on the dependent class to identify that it contains the foreign key. In your case, Customer could be the dependent and its key, Customer.UserId, should also be the foreign key. But both Keys must be declared using the same type:
public class User
{
[Key]
public int Id { get; set; }
public virtual Customer Customer { get; set; }
}
public class Customer
{
[Key, ForeignKey("User")]
public int UserId { get; set; }
public virtual User User{ get; set; }
}
I don't know how to resolve your problem using Data Annotations, but if you want to use Fluent Api, I think the configuration of the relationship would be like this:
modelBuilder.Entity<User>().HasOptional(u => u.Customer).WithOptionalPrincipal(c => c.User);
Update
I understand your escenario, but if you have the same columns that you show in your model, I think you should have a one-to-many relationship mapped in DB instead one-to-one. Try to map your relationship this way:
public class User
{
[Key]
public int Id { get; set; }
public string Password { get; set; }
public bool Locked { get; set; }
public string CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual Customer Customer { get; set; }
}
public class Customer
{
[Key]
[Column("Id", TypeName = "nvarchar")]
[StringLength(20)]
public string Id { get; set; } // nvarchar 20
[Required]
public string GivenName { get; set; } // nvarchar 100
[Required]
public string Surname { get; set; } // nvarchar 100
public virtual ICollection<User> Users { get; set; }
}
Remember map your properties with the same column'names that you have in DB.

EF Code first - Lazy Loading How to set up and access the joining table

public class Product
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public bool IsInStock { get; set; }
public string ImageUrl { get; set; }
public List<ProductOption> ProductOptions { get; set; }
public virtual Category Category { get; set; }
}
public class ProductOption
{
[Key]
public int Id { get; set; }
public string ProductOptionName { get; set; }
public string ProductOptionDescription { get; set; }
}
Now I know when your using Code First EF, so that the tables are created correctly. You need to do something like this.
modelBuilder.Entity<Product>().HasMany(p => p.ProductOptions).WithMany().Map(m =>
{
m.MapLeftKey("ProductId").MapRightKey("ProductOptionId").ToTable("SelectedProductOptionsInOrderedItem");
});
So....
Does this mean that if I do something like Product.ProductOptions I will be able to access all associated productoptions.
Is this the best way to set it up, or is there another way?
To enable lazy load and EF can create derived proxy types for your collection, that property should be declared this way:
public virtual ICollection<ProductOptions> ProductOptions { get; set; }
That should be enought. Other aspect is the mapping approach that you use. You choose fluent api, i prefer mapping by convention, but that is a matter of personal taste anyway.
Ok, Mapping by Conventions:
Is the ability of EF that from the name of entities and their properties along with their types, to map our model with the underlying data without providing any other information.
for example
public class Customer {
public long CustomerID {get; September;}
public string CustomerName {get; September;}
public Employee AssignedTo {get; September;}
}
With the previous model EF will map database with a table named Customer with:
. CustomerID bigint primary key column
. CustomerName nvarchar column
. Customer_EmployeeID foreign key to Employee table, with the datatype Corresponding to EmployeeID in that table.
You can read more Here

Issue with relational tables in Entity Framework

I have a one-to-many relationship of order to payment:
public class Order
{
[Key]
public Guid SerialNumber { get; set; }
public string OrderNumber { get; set; }
...
[ForeignKey("OrderNumber")]
public virtual ICollection<Payment> Payments { get; set; }
}
public class Payment
{
[Key]
public string SerialNumber { get; set; }
public string OrderNumber { get; set; }
...
public decimal Amount { get; set; }
}
Despite the records being available, the Payments collection always shows 0 elements. I've looked at the trace and the problem seems to be with the generated SQL query - it's trying to match Order.SerialNumber to Payment.OrderNumber.
How can I resolve this, preferably with data annotations? Thanks in advance!
it's trying to match Order.SerialNumber to Payment.OrderNumber.
Yes because that is exactly what you have modeled. ForeignKey attribute doesn't describe the name of foreign key property in the related table. It describes the name of foreign key property in the same table and it is used to pair navigation property with its key so the correct usage is:
public class Order
{
[Key]
public Guid SerialNumber { get; set; }
public string OrderNumber { get; set; }
...
public virtual ICollection<Payment> Payments { get; set; }
}
public class Payment
{
[Key]
public string SerialNumber { get; set; }
// Foreign key must have the same type as primary key in the principal table
public Guid OrderNumber { get; set; }
...
public decimal Amount { get; set; }
// Reverse navigation property to principal associated with foreign key
[ForeignKey("OrderNumber")]
public virtual Order Order { get; set; }
}
If you don't want navigation property in Payment you have to use fluent API to describe the mapping:
modelBuilder.Entity<Order>()
.HasMany(o => o.Payments)
.WithRequired()
.HasForeignKey(p => p.OrderNumber);
If you have existing database and your relation really targets OrderNumber column in the Order table it means it must be marked with unique constraint - such relation currently cannot be mapped in EF because it doesn't support unique constraints yet.

Categories