Entity framework, code first generation relationship between tables - sql-server

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]

Related

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.

Updating primary key in Entity Framework Code First

I want to update a mediate table's primary keys. This post suggests to take another primary key and don't change it, but we're using our tables in other non-EF projects, I didn't designed them and I'm not able to change them. Do I have any other option? Anything? Even deleting the old record and inserting a new one. I just don't know how to retrieve the old values.
This is my class:
public class ZChangeUnits : User
{
[Key]
[Column(TypeName = "VARCHAR", Order = 0), StringLength(4)]
public string CCode1 { get; set; }
[ForeignKey("CCode1")]
public virtual ZUnits ZUnits1 { get; set; }
[Key]
[Column(TypeName = "VARCHAR", Order = 1), StringLength(4)]
public string CCode2 { get; set; }
[ForeignKey("CCode2")]
public virtual ZUnits ZUnits2 { get; set; }
[Column(TypeName = "NUMERIC")]
[DecimalPrecision(18, 5)]
public decimal NZarib { get; set; }
}
UPDATE
I've posted the schema below, the left table is used for unit conversion. This is actually the suggested method in this answer.
I can't think of any other way to implement that. Whether I should update my table's design or some EF code will do the job. Any help and solution is welcome. :)

asp.net mvc entity data framework - when adding an item it tries to add another item even theres no relation

I was encountring an error when I try to add class to the database
DB.Trips.Add(trip);
I solved it by setting the navigation properties to null, but i never had to do that before and it worked just fine, so im wondering why is that, as it doesnt seem to me as a good approach and the problem might persist.
When I do the DB.SaveChanges(); I get an error. From the SQL profiler I found out that it is trying to insert a record into Countries table.
exec sp_executesql N'insert [dbo].[Countries](......
But Trips table doesn't even have Country property. There is a City property, which has Country. But why would it try to add that as well and how can I force it to insert only into Trips table ?
The data comes in via angular $http.post, is it possible its somehow related ?
Trip class city related attributes
public int CityOriginID { get; set; }
public int CityDestinationID { get; set; }
public virtual City CityDestination { get; set; }
public virtual City CityOrigin { get; set; }
City class
public partial class City
{
public int CityID { get; set; }
public string Name { get; set; }
public string CountryCode { get; set; }
public virtual Country Country { get; set; }
}
Thanks for any suggestions
Try adding a reference to your Trip entity in your City entity like
public virtual ICollection<Trip> Trips {get; set;}
to indicate your one-to-many relationship

Unique constraint with EFCodeFirst and SqlCe4

I'm writing an ASP.net MVC3 application using Entity Framework Code First and SqlCe4.
I have been designing several models, and found one that is turning out to be interesting. This is what I have so far:
public class Preference
{
public int PreferenceId { get; set; }
[Required]
public int StudentId { get; set; }
public virtual Student Student { get; set; }
[Required]
public int PresentationId { get; set; }
public virtual Presentation Presentation { get; set; }
[Required]
public int Rank { get; set; }
}
I however, need a unique constraint or index, because for a particular student, I want them to have to have a list of preferences, but the PresentationId needs to be unique for each student. Is there a way to do this via Code First or some validation attribute?
This sounds like I'm going down the branch of a many to many relationship with the Preference object being an intermediary, to add the Rank property. However, I can't seem to find how to make sure that the values are unique. Is the best way really to manually just add a unique index to the database outside of EF?
Currently(ie EF 4.1) EF does not have an Attribute or configuration mechanism to create unique indexes.
However if you are using Database Initializer you can create it manually
public class MyInitializer : IDatabaseInitializer<MyContext>
{
public void InitializeDatabase(MyContext context)
{
if (!context.Database.Exists() || !context.Database.ModelMatchesDatabase())
{
context.Database.DeleteIfExists();
context.Database.Create();
context.ObjectContext.ExecuteStoreCommand("CREATE INDEX IX_Preference_PresentationId ON Preference ( PresentationId )");
}
}
}
Or execute it outside the Initializer.
I'm not sure how long the feature has existed, but in EF5, you can use the CreateIndex and DropIndex method in your Up() and Down() methods. This allows you to create unique indexes, which function almost identically to unique constraints, in EF's own language.
public partial class UniqueIndexMigration
{
public override void Up()
{
// Create new unique index
this.CreateIndex("dbo.TableName", new[] { "Col1", "Col2", "Col3" }, true, "IX_TableName_Col1_Col2_Col3");
}
public override void Down()
{
// Drop unique index
this.DropIndex("dbo.TableName", "IX_TableName_Col1_Col2_Col3");
}
}
The true, seen above, is the parameter that specifies that it's a unique constraint. Sadly, these constraints are not honored when making further migrations later on (EF won't drop them for you if you change the underlying schema), but my hope is that by using the EF API, your code will get an upgrade for free when this feature is finally added.
Going with what Eranga was saying, I ended up making it work similarly, but like this:
I used the following code in my DataContext class:
public class StudentRegistrationContext : DbContext
{
public StudentRegistrationContext()
{
Database.SetInitializer(new StudentRegistrationDatabaseInitializer());
}
public DbSet<Student> Students { get; set; }
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Presenter> Presenters { get; set; }
public DbSet<Presentation> Presentations { get; set; }
}
In the Database Initializer class, I used the following:
public class StudentRegistrationDatabaseInitializer : DropCreateDatabaseIfModelChanges<StudentRegistrationContext>
{
protected override void Seed(StudentRegistrationContext context)
{
base.Seed(context);
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX UX_Preferences_StudentId_PresentationId ON Preferences (StudentId, PresentationId)");
}
}
See answear that implements the Unique constraint with a Custom ValidationAttribute:
https://stackoverflow.com/a/10566485/1133338

Resources