I've got a problem with a code-first model I've got. Data is now in the database so I can't re-seed the database using a DropCreateDatabaseIfModelChanges class, but I need to change one table so that a bigint column is not an IDENTITY(1,1). I've managed to do this using SSMS but now my EF code is saying it's out of date.
This is the code for the table in question:
public class Vote {
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public long FacebookUserId { get; set; }
[Required]
public Entity Entity { get; set; }
}
So I've changed my table schema, and my model (which I thought was the reflection of it, but I'm obviously wrong), but EF is still saying my model is out of date, and I can't re-seed the database to get it "perfect".
Any help would be much appreciated.
Thanks,
Benjamin
Using data annotation:
public class Customer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CustomerID { get; set; }
}
Using fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>().Property(c => c.CustomerID).HasDatabaseGeneratedOption(null);
base.OnModelCreating(modelBuilder);
}
referring to this post ...
It seems that entity framework expects by default that you insert into identity column.
to solve this try
modelBuilder.Entity<BOB>()
.HasKey(p => p.Id)
.Property(p => p.Id)
.StoreGeneratedPattern = StoreGeneratedPattern.None;
builder.Entity<BOB>().MapSingleType().ToTable("BOB");
or decorate your key in the POCO with ...
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Int64 PolicyID { get; set; }
Try add this to your OnModelCreating:
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
That should remove the exception that model is out of date but till this time you must always synchronize model and database manually.
Related
I am trying to configure a table of followers in a similar fashion as in this question
Followers Schema in Entity Framework
without an additional table, just via self-referencing, but the question was for EF
and I am using ef core.
With the configuration below I get the following table. I would like to change the name of the table as well as the names of the columns. Is this approach viable in ef core, or should I opt for an additional table?
public class User
{
public Guid Id {get;set;}
public ICollection<User> Followers { get; set; }
public ICollection<User> Following { get; set; }
}
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasMany(x => x.Followers).WithMany(x => x.Following);
}
I have entities A and B and I want to create 2 distinct 1-1 associations between A and B. A should play the role as principal. Like this:
public class A
{
public int Id {get; set;}
public B B1 {get; set;}
public B B2 {get; set;}
}
public class B
{
public int Id {get; set;}
}
Since EF does not support one-to-one foreign key associations I cannot create a working model/database with EF. To my this sounds like a serious limitation. Are there any plans to support such associations in an upcoming version of EF?
What is the best workaround for to get this working. I know about creating two one-2-many associations. However, that would make B the principal and gives me problems with cascading deletes.
Thanks for replying to my question. Below is an example of what I want to do, i.e., create two (or more) 1-to-1 associations between an entity A and another entity B. Is this something that EF could support in vNext, or else, why would it be a bad idea?
Thanks again,
Merijn
public class A
{
public int Id {get; set;}
public int B1_Id {get; set;}
public B B1 {get; set;}
public int B2_Id {get; set;}
public B B2 {get; set;}
}
public class B
{
public int Id {get; set;}
}
public class SampleContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<A>().HasKey(c => c.Id);
modelBuilder.Entity<B>().HasKey(c => c.Id);
modelBuilder.Entity<A>().HasRequired(c => c.B1).WihOptional().ForeignKey(x=>x.B1_Id);
modelBuilder.Entity<A>().HasRequired(c => c.B2).WihOptional().ForeignKey(x=>x.B2_Id);
}
}
If "v-Next" is Entity Framework 6, then no, it apparently won't support one-to-one foreign key associations, as you can see on the roadmap for all features planned for EF 6.
You can also see that Unique Constraint support is not on the roadmap and still marked as "Under Review" on UserVoice.
Because a one-to-one foreign key association is basically a one-to-many association with a unique constraint on the foreign key column I would expect that one-to-one FK associations won't be implemented before Unique Constraint support is available. It's especially required if you want that A is the principal in your two relationships. Currently EF does not support relationships where the principal's key is not the primary key but some column with unique constraint.
In this blog post the feature is described and mentioned that it is "postponed", so let's hope for EF 7.
Perhaps it is a terminology issue.
In Code first EF, EF doesnt allow you to have 1:1 relationships with Principal and Dependent both with foreign keys to each other
or with the dependent having its own primary key unrelated to Principal.
With your example it looks like that it is a case of 2 navigation properties required.
And strictly speaking it is not 1:1. since you have 2 relationships to the same table.
you have 2 relationships of type 1:1.. EF sees this as many to 1.
If you have a true 1:1 relationship, EF will want the dependent to have the same Primary Key as the primary.
You can define Multiple NAVIGATION properties on Both Principle and dependent, which result in indexes.
So you may wish to investigate Many to 1 configurations
If you want the Primary to have an OPTINAL Foreign Key at DB level, You would need to ADD this FK later during migration or with script.
But arguably this is best seen as business logic/rule check rather than an OPTIONAL FK on principal.
So yes there are limitations in matching exactly what is possible on the DB.
But it is questionable is actually necessary in a code first scenario.
Neat trick here btw is to model in DB exactly what you want on Code first.
There use the EF Powertool nuget to reerse engineer Codefirst from DB.
EG mini DB with just the desired table relationships.
make a new project in Solution. Install Entity Framework Powertools.
Then use right click option in new project to "reverse engineer code first from DB".
It shows how to build that in code first if it can.... :-)
What I think you wanted to achieve... see code sample (sorry if I misunderstood the point your are making) code should execute if NUGET is loaded
using System.Data.Entity;
namespace EF_DEMO
{
class FK121
{
public static void ENTRYfk121(string[] args)
{
var ctx = new Context121();
ctx.Database.Create();
System.Console.ReadKey();
}
}
public class Main
{
public int MainId { get; set; }
public string BlaMain { set; get; }
public int? Sub1Id { set; get; } // Must be nullable since we want to use EF foreign key
public int? Sub2Id { set; get; } // Must be nullable since we want to use EF foreign key
public virtual Sub Sub1 { get; set; } // Reverse navigation
public virtual Sub Sub2 { get; set; } // Reverse navigation
// you may also need
public virtual ICollection<Sub> Subs { get; set; }
}
public class Sub
{
public int SubId { get; set; } // Deliberately DIFFERENT KEY TO MAIN.... not 1:1 so this is possible
public string blasub { set; get; }
public int MainId { set; get; } //set in API , this the FK
public virtual Main Main { get; set; } // van to Principal
}
public class Context121 : DbContext
{
static Context121()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>());
}
public Context121()
: base("Name=Demo") { } // webconfig required to match
public DbSet<Main> Mains { get; set; }
public DbSet<Sub> Subs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Main>().HasKey(t => t.MainId)
.HasOptional(t => t.Sub1)
.WithMany()
.HasForeignKey(t=>t.Sub1Id) ; // tell EF the field is in POCO, use this please, otherwise it will create it.
modelBuilder.Entity<Main>()
.HasOptional(t => t.Sub2).WithMany()
.HasForeignKey(t=>t.Sub2Id);
modelBuilder.Entity<Sub>()
.HasKey(t => t.SubId)
.HasRequired(q => q.Main)
.WithMany()
.HasForeignKey(t => t.MainId);
}
}
}
WEBCONFIG....
<connectionStrings>
<add name="Demo" connectionString="Data Source=localhost;Initial Catalog=Demo;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework"
providerName="System.Data.SqlClient" />
</connectionStrings>
Explain what problem do you need to resolve? This is sample of one-to-one mapping in EF 5.0
class Program
{
static void Main(string[] args)
{
using (var context = new SampleContext())
{
var mainEntity = new MainEntity();
mainEntity.DetailEntity = new DetailEntity();
context.SaveChanges();
}
}
}
public class SampleContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MainEntity>().HasKey(c => c.Id);
modelBuilder.Entity<DetailEntity>().HasKey(c => c.Id);
modelBuilder.Entity<MainEntity>().HasOptional(c => c.DetailEntity).WithRequired(p => p.MainEntity);
modelBuilder.Entity<DetailEntity>().HasRequired(c => c.MainEntity).WithOptional(p => p.DetailEntity);
}
public virtual DbSet<MainEntity> MainEntities { get; set; }
public virtual DbSet<DetailEntity> DetailEntities { get; set; }
}
public class MainEntity
{
public int Id { get; set; }
public DetailEntity DetailEntity { get; set; }
}
public class DetailEntity
{
public int Id { get; set; }
public MainEntity MainEntity { get; set; }
}
I'm new to Entity Framework and C#/.Net and trying to create a TPH inheritance model, I'm not sure if I should be or not, so if not, please advise,
Here's the model:
public abstract class Vote
{
public int VoteID { get; set; }
public int UserID { get; set; }
public bool Value { get; set; }
public DateTime DateCreated { get; set; }
public User User { get; set; }
}
public class ProjectVote_ : Vote
{
public int ProjectID { get; set; }
public virtual Project Project { get; set; }
}
public class CommentVote_ : Vote //There are three more like this, votes for different hings
{
public int CommentID { get; set; }
public virtual Comment Comment { get; set; }
}
Now the Project model (comment and model is similar)
public class Project
{
public int ProjectID { get; set; }
public string Title { get; set; }
public virtual ICollection<Vote> Vote { get; set; }
}
What happens is that ICollection creates a database column Project_ProjectID as the foreign key in the Vote table (I think) instead of using the ProjectID I defined. How do I fix it or should I model it differently. If the fluent API is the way to fix it, I don't know how to do that.
In the end I want to be able to use one table to store 5 different types of votes.
When you have related entities you don't need to have a property to store the FK in your model. Entity framework knows that it needs to make a FK to the Project table in ProjectVote when it detects Project in your ProjectVote_ model. Same thing with User and UserId and Comment and CommentId. You don't need to have a property that stores the FK in your model.
You are getting the FK column with the name you don't like "Project_ProjectID" because Entity framework is detecting that it needs to create a FK for your navigation property "Project". It's using it's own naming convention to create the column hence "Project_ProjectID".
If you want to provide your own name for the column override OnModelCreating in your DBContext class and add this fluent mapping.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>()
.HasMany(p => p.Vote)
.HasRequired(v => v.Project) //or .WithOptional(v => v.Project)
.Map(m => m.MapKey("ProjectId")); //or any other name you want.
}
And for the future this is a helpful reference for how to use the Fluent API. For example here is some documentation on how to custimize TPH with fluent.
Hope that helps!
Firebird 2.5
Entity Framework 5
FirebirdClientDll 3.0.0.0
Hi, I'm trying to access my legacy database with the Entity Framework (Code First).
I got the problem that the database does not use foreign keys...
public class CUSTOMERS
{
public int CUSTOMERID { get; set; }
public string NAME{ get; set; }
}
public class INVOICES
{
public int INVOICEID{ get; set; }
public int CUSTOMERID{ get; set; }
public virtual CUSTOMERS CUSTOMERS { get; set; }
}
public class INVOICEContext : DbContext
{
public DbSet<CUSTOMERS> CUSTOMERS{ get; set; }
public DbSet<INVOICES> INVOICES{ get; set; }
public INVOICEContext(DbConnection connectionString) : base(connectionString, false)
{
Database.SetInitializer<INVOICEContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
/*modelBuilder.Entity<INVOICES>().HasRequired(b => b.CUSTOMERS)
.WithMany()
.Map(p => p.MapKey("INVOICEID"));*/ //Doesn't work because INVOICEID is defined
modelBuilder.Entity<INVOICES>().HasKey(a => new { a.INVOICEID, a.CUSTOMERID});
modelBuilder.Entity<CUSTOMERS>().HasKey(a => new { a.CUSTOMERID });
base.OnModelCreating(modelBuilder);
}
}
Normally I could remove the property CUSTOMERID from the class INVOICES, but in this case it is part of the primary key...
I found many threads which suggested to use IsIndependent, but it seems to be removed from the Entity Framework 5 (or 4.1).
I hope you can understand my poor English and maybe give me a hint what I'm doing wrong ^^
I don't know what you mean with "the database does not use foreign keys". So, maybe the following is not the answer you are looking for. But I'd say that you can use your relationship mapping that is commented out in your code if you replace ...MapKey... by HasForeignKey and use CUSTOMERID instead of INVOICEID as the foreign key property:
modelBuilder.Entity<INVOICES>()
.HasRequired(b => b.CUSTOMERS)
.WithMany()
.HasForeignKey(b => b.CUSTOMERID);
The model and the rest of the mapping is fine in my opinion. Your relationship is an identifying relationship (that means that the foreign key is part of a composite primary key) which is a valid mapping with Entity Framework.
Try this ...
modelBuilder.Entity<INVOICES>()
.HasRequired(i => i.CUSTOMERS)
.WithMany()
.HasForeignKey(i => i.CUSTOMERID);
Very simply I am using Entity Framework 4.1 code first and I would like to replace my [ForeignKey(..)] attributes with fluent calls on modelBuilder instead. Something similar to WithRequired(..) and HasForeignKey(..) below which tie an explicit foreign key property (CreatedBySessionId) together with the associated navigation property (CreatedBySession). But I would like to do this for a one to one relationsip instead of a one to many:
modelBuilder.Entity<..>().HasMany(..).WithRequired(x => x.CreatedBySession).HasForeignKey(x => x.CreatedBySessionId)
A more concrete example is below. This works quite happily with the [ForeignKey(..)] attribute but I'd like to do away with it and configure it purely on modelbuilder.
public class VendorApplication
{
public int VendorApplicationId { get; set; }
public int CreatedBySessionId { get; set; }
public virtual Session CreatedBySession { get; set; }
}
public class Session
{
public int SessionId { get; set; }
[ForeignKey("CurrentApplication")]
public int? CurrentApplicationId { get; set; }
public virtual VendorApplication CurrentApplication { get; set; }
public virtual ICollection<VendorApplication> Applications { get; set; }
}
public class MyDataContext: DbContext
{
public IDbSet<VendorApplication> Applications { get; set; }
public IDbSet<Session> Sessions { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Session>().HasMany(x => x.Applications).WithRequired(x => x.CreatedBySession).HasForeignKey(x => x.CreatedBySessionId).WillCascadeOnDelete(false);
// Note: We have to turn off Cascade delete on Session <-> VendorApplication relationship so that SQL doesn't complain about cyclic cascading deletes
}
}
Here a Session can be responsible for creating many VendorApplications (Session.Applications), but a Session is working on at most one VendorApplication at a time (Session.CurrentApplication). I would like to tie the CurrentApplicationId property with the CurrentApplication navigation property in modelBuilder instead of via the [ForeignKey(..)] attribute.
Things I've Tried
When you remove the [ForeignKey(..)] attribute the CurrentApplication property generates a CurrentApplication_VendorApplicationId column in the database which is not tied to the CurrentApplicationId column.
I've tried explicitly mapping the relationship using the CurrentApplicationId column name as below, but obviously this generates an error because the database column name "CurrentApplicationId" is already being used by the property Session.CurrentApplicationId:
modelBuilder.Entity<Session>().HasOptional(x => x.CurrentApplication).WithOptionalDependent().Map(config => config.MapKey("CurrentApplicationId"));
It feels like I'm missing something very obvious here since all I want to do is perform the same operation that [ForeignKey(..)] does but within the model builder. Or is it a case that this is bad practise and was explicitly left out?
You need to map the relationship as one-to-many and omit the collection property in the relationship.
modelBuilder.Entity<Session>()
.HasOptional(x => x.CurrentApplication)
.WithMany()
.HasForeignKey(x => x.CurrentApplicationId)