EF Code First: Does not update foreign key constraint name when property is changed - entity-framework

I probably found a bug... at least it's annoying to me so I would appreciate if someone confirms this:
public int PriorityConfigurationSettingId { get; set; }
[ForeignKey("PriorityConfigurationSettingId")]
public virtual PriorityConfigurationSetting
PriorityConfigurationSetting{get;set; }
to
public int PriorityConfigurationSettingId { get; set; }
[ForeignKey("PriorityConfigurationSettingId")]
public virtual LookUp PriorityConfigurationSetting { get; set; }
When I change the name of a foreign key entity name from PriorityConfigurationSetting to LookUp. After done the model changes i try to get the script through EF Code Fist Migration, I didn't get any changes.

Related

Entity Framework code-first : How to fix error with self-reference foreign key in SQL using Annotations

I have trouble with the database, I use a table t_CTDaotao sc_HeNganh. The problem here is that the self-referencing key t_CTDaotao1 can only refer to sc_HeNganh1, and the key t_CTDaotao2 cannot reference sc_HeNganh2, more correctly it only reference 1 key, not multiple keys
enter image description here
enter image description here
You need to put the [ForeignKey] attributes on the navigation properties, not the foreign key columns.
Please try this:
public int MaHN { get; set; }
public int MaKhoi { get; set; }
[ForeignKey("sc_HeNganh")]
public virtual sc_HeNganh sc_HeNganh { get; set; }
[ForeignKey("sc_Khoilop")]
public virtual sc_Khoilop sc_Khoilop { get; set; }

ForeignKey to a non PrimaryKey but still unique

I got 2 classes i want to be able to create a ForeignKey to a field that is not the primarykey of the class
my BeerDispense need to point to my Master with an int with the field called MacAdrInt
This way i make my MacAdrInt field point to the primarykey of my master, but i want it to point to MacAdrInt, is this possible or do i need to make it my primarykey?
public class Master
{
[Key]
public long Id { get; set; }
public string MacAdr { get; set; }
public long MacAdrInt { get; set; }
...
}
public class BeerDispense
{
public long Id { get; set; }
[ForeignKey("MacAdrInt")]
public Master Master { get; set; }
...
}
i want it to point to MacAdrInt, is this possible or do i need to make it my primarykey?
In EF Core this is possible using Alternate Keys. In EF6 you need configure MacAdrInt as your Key property. It does not have to be the real primary key, but EF6 only supports one Key per entity.

EF creating an unwanted field in database

I've hit a snag while building a .net mvc site. I have 2 related objects and am struggling with properly linking them. Specifically:
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostCode { get; set; }
[ForeignKey("AddressCategory")] // <-- EF adds field to below object's table
public int AddressCategoryId { get; set; }
public virtual AddressCategory AddressCategory { get; set; }
}
public class AddressCategory
{
public int AddressCategoryId { get; set; }
public string Description { get; set; }
}
Adding the [ForeignKey] data annotation to the Address object results in EF adding an Address_AddressId column to the AddressCategory table, which I don't want (or need) to happen.
I've tried to omit the ForeignKey attribute, but then I run into other errors because .net can't link the tables (e.g. Unknown column 'Extent1.AddressId' in 'field list'). Additionally, I wouldn't be able to use:
var addresses = db.Addresses.Include(l => l.AddressCategory);
Is there any way to link the 2 tables without EF adding an additional column to the AddressCategory table?
Thank you to #cloudikka for responding. After much trial-and-error I seem to have gotten it to work simply by omitting any ForeignKey reference from either object. I let EF rebuild the database and perform all scaffolding (CRUD forms) and they have been created perfectly.
My take-away is that foreign key attributes should be used for parent-child relationships, but not for look-up tables. I clearly have much to learn about asp.net mvc!

Entity Framework -- Two Properties Referencing Same Table

I'm continuing my venture with Entity Framework, but now I'm stuck again. I've two small classes:
public class Machine
{
public int MachineID { get; set; }
public string Name { get; set; }
[Required]
[ForeignKey("InstalledByID")]
public virtual Employee InstalledBy { get; set; }
public int InstalledByID { get; set; }
[Required]
[ForeignKey("LastServicedID")]
public virtual Employee LastServiced { get; set; }
public int LastServicedID { get; set; }
}
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
}
I'm trying to set two properties: InstalledBy and LastServiced. Both of these properties are instances of an Employee class. Additionally, I could care less that there are two REVERSE properties on the Employee class that tells a list of machines installed as well as machines repaired. When I try to Update-Database after a Migration, I get an error. I thought the ForeignKeyAttribute was the key, but apparently it's not working for me. Here is the error:
Introducing FOREIGN KEY constraint 'FK_dbo.Machines_dbo.Employees_InstalledByID' on table 'Machines' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
Also, I've tried dabbling in the OnModelCreating and FluentAPI, but my attempts did not work. Any pointers as to what I'm doing wrong and how to fix it would be greatly appreciated. Thank you, all.

Deletion of entire entity graph, including relationships, using EF Code First

I have classes that are structured like the following:
public class Forecast
{
[Key]
[ForeignKey("Stop")]
public string Abbreviation { get; set; }
public virtual Stop Stop { get; set; }
public virtual List<Direction> Directions { get; set; }
}
public class Direction
{
public int DirectionId { get; set;}
public string Abbreviation { get; set;}
public virtual Forecast Forecast { get; set;}
public virtual List<Transport> Transports { get; set;}
}
public class Transport
{
public int TransportId { get; set; }
public int DirectionId { get; set;}
public virtual Direction Direction { get; set;}
}
public partial class Stop
{
[Key]
public string Abbreviation { get; set; }
public virtual Forecast Forecast { get; set; }
}
I developed these classes and used EF Code First 4.1 to generate the database. CF does appear to properly create all of the primary and foreign key relationships between the classes within the database (MSSQL).
My problem is when I want to delete a Forecast. I thought I do could something like the following:
using (MyContext ctxt = new MyContext())
{
// get a forecast, somehow, not really important
// The one assumption is I'm absolutely sure it's
// Abbreviation key already exists in the database
// and the list of Forecasts.
Forecast f;
ctxt.Forecasts.Remove(f);
}
This deletes the top-level object from the database just fine. However, all of its child objects - all of the directions and transports - remain in the database and become orphaned (their key relationship column gets set to null. I expect that but I DON'T know why they're not just deleted). I have resorted to recursing down the object graph and calling Remove on every object from its appropriate DbSet in ctxt, but that seems like... the wrong way to do it.
What am I missing here?
Why can't I just say
ctxt.Forecasts.Remove(f);
and be done with it?
Edit:
#Ladislav gave me the right answer - I
needed to add [Required] to the
Abbreviation property on Direction.
However, I am still forced to actually
load the child entities for this to
work - doing something as simple as
Direction d = f.Directions[0];
will cause the delete to actually
delete the child entities. I'm well
aware that this is due to lazy
loading. I thought the point of the
FK relationship and ON CASCADE DELETE
was that you wouldn't have to actually
load the entities to delete them?
Again I seem to be missing something simple.
#Eranga is right that this is done by ON DELETE CASCADE setting on relation in the database BUT you are using code first approach and EF creates database for you so the problem here is that your model is not correctly defined because EF didn't create cascading rule for you.
Why? Because of this:
public class Direction
{
public int DirectionId { get; set; }
public string Abbreviation { get; set; }
public virtual Forecast Forecast { get; set; }
public virtual List<Transport> Transports { get; set; }
}
Abbreviation is FK property and it is nullable! So EF looks at your model and it sees that you defined Direction entity which can have Abbreviation set to null and because of that it can exists orphaned. Change it to:
public class Direction
{
public int DirectionId { get; set; }
[Required]
public string Abbreviation { get; set; }
public virtual Forecast Forecast { get; set; }
public virtual List<Transport> Transports { get; set; }
}
and removing Forecast will delete all related Direction instances and Transport instances. Stop is different story because it is parent entity to Forecast so it will never be removed with Forecast.
Edit:
One more point - you don't want to add ON DELETE CASCADE to your relations manually because EF have to know about enabled cascade deletes. EF use this information in case where you have related entities loaded.
If you place the rule manually into the database you must use fluent mapping and tell EF about this rule as well. Once you force cascade delete in fluent api you don't need to make it manually in the database - it will be created automatically during database recreation.
You can easily achieve this by setting ON DELETE CASCADE when you create foreign keys in the Database.