Entity Framework fails to update SQL Server database - sql-server

I have a problem with a constraint in my database. A StairWay class uses a strongly typed property called Tread. I receive a message that the constraint does not exist when I try to update-database but the code below tells me it is created. I am using Entity Framework, SQL Server with ASP.NET Core 3.1.
Screenshot of the error message:
//Classes I have created
public class StairWay
{
public StairTread Tread { get; set; }
public int StairTreadId { get; set; }
public int StairWayId { get; set; }
}
public class StairTread
{
public int StairTreadId { get; set; }
public int StairWayId { get; set; }
}
// SQL code generated
ALTER TABLE [dbo].[StairTread]
ADD CONSTRAINT [FK_StairTread_StairCases_StairWayId]
FOREIGN KEY ([StairWayId])
REFERENCES [dbo].[StairWays] ([StairWayId]) ON DELETE CASCADE;

Related

The collection argument 'foreignKeyPropertyNames' must contain at least one element

I have two models with certain properties:
public class Issue {
public int Id { get; set; }
}
public class Action {
public int Id { get; set; }
}
This was the last working code. Then as I forgot to add Issue as a foreign key property to Action I did it and it became:
public class Action {
public int Id { get; set; }
public Issue Issue { get; set; }
public int IssueId { get; set; }
}
The solution built, migration up method created and ef update database failed with the following error:
Applying migration '20180220102738_Action.issue'. Failed executing
DbCommand (20ms) [Parameters=[], CommandType='Text',
CommandTimeout='30'] ALTER TABLE [Actions] ADD CONSTRAINT
[FK_Actions_Issues_IssueId] FOREIGN KEY ([IssueId]) REFERENCES
[Issues] ([Id]) ON DELETE CASCADE; System.Data.SqlClient.SqlException
(0x80131904): Introducing FOREIGN KEY constraint
'FK_Actions_Issues_IssueId' on table 'Actions' may cause cycles or
multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO
ACTION, or modify other FOREIGN KEY constraints.
Then I tried to change the onDelete: ReferentialAction.Cascade to onDelete: ReferentialAction.SetNull or anything else but nothing worked and btw I don't understand what could be its problem, this would be the third foreign key on this table.
My next step was to remove last migration but it started to complain about the following:
System.ArgumentException: The collection argument
'foreignKeyPropertyNames' must contain at least one element. at
Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty[T](IReadOnlyList1
value, String parameterName) at
Microsoft.EntityFrameworkCore.Metadata.Builders.ReferenceCollectionBuilder2.HasForeignKey(String[]
foreignKeyPropertyNames) at
ISSupport.Models.ISSupportContext.<>c.b__69_7(EntityTypeBuilder`1
b) in
I could roll back to the last commit but I don't see what did I do and what should I avoid in the next round. Google didn't help with this error.
.NET Core 2.0
EF Core 2.0
Sql Server 13.0.1742
Update
I had to do a rollback and added the foreign key again. It complained again about multiple cascade paths and now I changed it in the migration Up() method to onDelete: ReferentialAction.NoAction and run update successfully. I don't know what I had f*#!d up before and still need an explanation why do I have to set ReferentialAction.NoAction
This is what you had to do:
public class Issue
{
public int Id { get; set; }
}
public class Action
{
public int Id { get; set; }
[ForeignKey("IssueId")]
public Issue Issue { get; set; }
public int IssueId { get; set; }
}
You have to define what is going to be your foreign key property.
In migration Up() method I had to switch the Foreign key ReferentialAction to onDelete: ReferentialAction.NoAction

Entity Framework Core Migration fails in Case of Change to ValueGenerationStrategy

I have annotated some of my model classes' keys with [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
and added a migration.
When running Update-Database I keep getting following error message:
To change the IDENTITY property of a column, the column needs to be dropped and recreated.
I also tried to Update-Database with a complete new database, to no avail as the error is the same.
When changing the identity property in SQL Server Management Studio, I do not get such error but I would like to avoid a mix of code and DB first approach.
Is there a way to either
force the update to drop and recreate the column
or drop and recreate the table ?
EDIT1:
To answer a question from the comments. My model class before looked like:
public partial class MyModel
{
[Key]
public int Id { get; set; }
[MaxLength(70)]
public string Name { get; set; }
public string Description { get; set; }
...
}
This is my model class after adding the annotation:
public partial class MyModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(70)]
public string Name { get; set; }
public string Description { get; set; }
...
}

How to debug Entity Framework Code First database deployment error?

How do I debug an error with my Entity Framework Code First database deployment?
I'm using EF 6.1.3. I'm trying to deploy a database to Azure that includes the following model:
public class DriverLog
{
public int ID { get; set; }
[Required]
public DateTime LogDate { get; set; }
public int RouteID { get; set; }
public virtual Route Route { get; set; }
public int DriverID { get; set; }
[ForeignKey("DriverID")]
public virtual Employee Driver { get; set; }
public int DispatcherID { get; set; }
[ForeignKey("DispatcherID")]
public virtual Employee Dispatcher { get; set; }
}
The deployment succeeds, but when I try to access the database, I get the following error:
{"Message":"An error has occurred."}
If I remove the last two fields -- DispatcherID and Dispatcher -- I do not get this error.
For some reason, EF does not like my including these two fields, but I don't know why, and I don't know how to go about debugging this.
I was able to resolve the problem like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<DriverLog>()
.HasRequired(o => o.Dispatcher)
.WithMany()
.WillCascadeOnDelete(false);
}
Credit for this solution goes to: Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
Do check primary key constraint for 'DispatcherID', basicaly the order its creating the table, as you are using 'DropCreateDatabaseIfModelChanges'.
Also inject some custom error catch, to have detail error information.

Entity framework, Data annotations [DatabaseGenerated(DatabaseGeneratedOption.Identity)] and sequential GUID

I'm trying to use the entity framework to communicate with my existing DB. This is thus DB first. Using sql server and c#. The problem is that I would like to use a sequential GUID, generated by the database.
Each time I run the code, my controller pastes the GUID assigned to lutRoughagePhysicalSiloId to the DB (most of the time lutRoughagePhysicalSiloId is just an empty GUID (000..) since I don't fill it). As far as I can see, this should not be happening since I use [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
Any Ideas?
SQL code
CREATE TABLE [dbo].[lutRoughagePhysicalSiloType]
(
[RoughagePhysicalSiloTypeId] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY UNIQUE DEFAULT NEWSEQUENTIALID(),
[PhysicalSiloTypeName] NVARCHAR(50) NOT NULL UNIQUE
)
(Notice the Default value newsequentialId() that gets generated as default by sql server)
Automatic created modelview (DB first):
namespace guiIlvoDairyCowBarn.Models
{
using System;
using System.Collections.Generic;
public partial class lutConcentratePhysicalSiloType
{
public lutConcentratePhysicalSiloType()
{
this.lutConcentratePhysicalSiloes = new HashSet<lutConcentratePhysicalSilo>();
}
public System.Guid ConcentratePhysicalSiloTypeId { get; set; }
public string PhysicalSiloTypeName { get; set; }
public virtual ICollection<lutConcentratePhysicalSilo> lutConcentratePhysicalSiloes { get; set; }
}
}
Buddy class
namespace guiIlvoDairyCowBarn.Models
{
[MetadataType(typeof(lutRoughagePhysicalSiloMD))]
public partial class lutRoughagePhysicalSiloType
{
public class lutRoughagePhysicalSiloMD
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public System.Guid RoughagePhysicalSiloTypeId { get; set; }
[Required, DisplayName("Physical silo type")]
public string PhysicalSiloTypeName { get; set; }
public virtual ICollection<lutRoughagePhysicalSilo> lutRoughagePhysicalSiloes { get; set; }
}
}
}
what is a Buddy class suppose to mean?
Using both [Key] and the [DatabaseGenerated(DatabaseGeneratedOption.Identity)] should work and ignore any user provided value. After saving to the DB the property should have the DB generated Guid.
Your class lutConcentratePhysicalSiloType has no EF data annotations and if saved would take the values you provided. NewSequentialId() is a default and without any EF data annotations the DB row will get whatever the value you specify in the C# class.

Entity framework, code first generation relationship between tables

I'm learning EF with MVC and following
video
They saying that line :
public ICollection<Chirp> Chirps { get; set; }
adds the relationship between the two models, but I don't see any difference so far when looking at both tables columns and keys after regenerating tables WITHOUT this line. I'm missing something as this kind of relationship is mentioned in all the tutorials.
public class User
{
public int Id { get; set; }
public String Name { get; set; }
public ICollection<Chirp> Chirps { get; set; }
}
public class Chirp
{
public int Id { get; set; }
public string Message { get; set; }
public User User { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Chirp> Chirps { get; set; }
public DbSet<User> Users { get; set; }
}
In other words, does public ICollection Chirps { get; set; } tell EF to do anything with db structure ?
Thank you!
This should be generating an additional table that tracks the User to Chirps relationship. Look in your database for a User_Chirps or UserChirps table that should have two columns, User_Id and Chirp_Id. Additionally, I just noticed that your id property is using a lowercase i for id. I believe that the conventions in Entity Framework are expecting a property name of Id with an uppercase I. So you may want to try changing that as well.
Seems that difference is in constraint of the Chirps table. Without public ICollection Chirps { get; set; }
its:
ALTER TABLE [dbo].[Chirps] WITH CHECK ADD CONSTRAINT **[Chirp_User]** FOREIGN KEY([User_id])
REFERENCES [dbo].[Users] ([id])
while with it its :
ALTER TABLE [dbo].[Chirps] WITH CHECK ADD CONSTRAINT **[User_Chirps]** FOREIGN KEY([User_id])
REFERENCES [dbo].[Users] ([id]

Resources