Is it possible to alter tables in code-first migrations with nocheck constraints? I haven't found any way to do this except of getting SQL script via Update-Database -Script and modifying the sql statements.
You can try creating your own MigrationSqlGenerator and use it with migrations (you can set custom SQL generator in DbMigrationsConfiguration) - I think it should be enough to inherit SqlServerMigrationSqlGenerator and add NOCHECK after adding foreign key = overriding Generate(AddForeignKeyIperation operation).
Anyway using NOCHECK with EF is way to disaster. If you want to have database without checked constraints don't use EF because it will crash every time it reaches inconsistency.
Another way to do it for one-off occasions is to call the SQL for creating the FK manually, like so, from within your Up() method:
// AddForeignKey("dbo.EFElementGroupEntries", "ConstraintCode", "dbo.EFElementConstraints", "Code");
Sql(#"ALTER TABLE [dbo].[EFElementGroupEntries] WITH NOCHECK
ADD CONSTRAINT[FK_dbo.EFElementGroupEntries_dbo.EFElementConstraints_ConstraintCode] FOREIGN KEY([ConstraintCode])
REFERENCES[dbo].[EFElementConstraints]([Code])");
Sql(#"ALTER TABLE [dbo].[EFElementGroupEntries] CHECK CONSTRAINT [FK_dbo.EFElementGroupEntries_dbo.EFElementConstraints_ConstraintCode]");
If the goal is to create a required foreign key but update-database fails due to existing data, just do it in two stages. For example, suppose I want to add a foreign key for TEAM in a PLAYER class for a 1:m relationship where all players must be assigned to a team. Assuming all classes have integer identity primary keys...
1. Add the usual two properties to PLAYER but use a nullable int for the foreign key. ie:
public int? TeamID { get; set; }
public virtual Team Team { get; set; }
Add a migration and update the database. All of the TeamID values will be null but you will be allowed to create the relationship.
Next, fix your data so every player is assigned a valid TeamID. If you are seeding player data, you will need to supply TeamID values there as well.
Modify the PLAYER class so the int is no longer nullable:
public int TeamID { get; set; }
Add another migration and update the database again. You should be good to go.
Related
I would like to add new column in my existed table using domain class but it is not happening. if I use create-drop in application.yml file then it works but at the same time I lost my data. I needed to keep the data as well as I needed to add new column by updating domain class property in grails 3.3.0 and SQL Server 2012
package com.alumni
class Student
{
String studentId
String studentName
String age
static constraints = {
}
}
Database is not updating with column address
It's unclear from your code snippet, but it sounds like you're trying to add
String address
Note that columns are made NOT NULL by default, so if data exists in the table, it's attempting to add a non-nullable column, with null data on every row, so the column will fail to create. You need to allow this column to be nullable in the constraints block as well
static constraints = {
address(nullable: true)
}
If you add that, the column should create successfully.
I have an MVC application using Code First data migrations and now, long after making a table, I'd like to change the PK column to not be an auto-generated Identity column. But I get the impression I just can't do this without having CodeFirst delete the table somehow (which will be hard given all the dependencies) and recreate it? Really wishing I didn't have to do that.
What I've tried:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int AssessmentID { get; set; }
and this in OnModelCreating():
modelBuilder.Entity<Assessment>()
.Property(e => e.AssessmentID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
When doing add-migration, it doesn't add anything. I tried manually adding this line but it does not update the db:
AlterColumn("dbo.Assessment", "AssessmentID", c => c.Int(nullable: false, identity:false));
I've concluded that this is indeed not possible. Like the post below says, there is no SQL Alter command to change the Identity status on a column, so CodeFirst can't create one. I plan to remove all migration files and rescaffold (things have gotten messy in other ways).
Remove Identity from a column in a table
I have a Member class:
public class Member
{
// key
public Guid UserId { get; set; }
// some other fields
}
Also I have a aspnet_Users table with has UserId primary column.
We can:
1). Add additional property MembershipUser to the Member object and get it's value by calling Membership.GetUser(this.UserId) method.
Also I've add
context.Database.ExecuteSqlCommand("ALTER TABLE [dbo].[Members] WITH CHECK ADD CONSTRAINT [FK_Members_aspnet_Users] FOREIGN KEY([UserId]) REFERENCES [dbo].[aspnet_Users] ([UserId])");
to the DataContext.Seed() method to ensure that Member can not be added without aspnet_Users account.
2). Use fluent API in OnModelCreating. If this a good case how to map them correctly?
What's the best choice? Any thoughts?
No matter how I tried to avoid it, I've found the best approach is to implement my own MembershipProvider and have it use my model, rather than trying to shoehorn my model into the built-in membership provider.
If you are going down the other route you have to map the ASP.NET Membership tables to your domain and derive your Member class from the ASP_User class (or vice versa if you want to ensure that all Users you create are Members). In the end, I've discovered that although it seems like more effort up front, implementing MembershipProvider is the easier approach.
You don't. Don't add foreign key constraints against the aspnet_* tables. It's a recipe for trouble. Membership is plug-in type system, and you have to treat it as a black box.
Simply lookup the data in your tables with the MembershipUser.ProviderUserKey as it's value. Something like this:
from m in Member where UserID == (Guid)Membership.GetUser().ProviderUserKey select t;
I have same type of tables
ProductCodeTable, CountrycodeTable etc
All have key, value as their fields
When I use entity frame work,
Can I have a single entity for all these tables such that I can formulate different queries to get data from different tables?
You can create a base class for all of them and create sub class for each entity
public abstract class LookUpEntity
{
[Key]
public int Key { get; set; }
[Required]
public string Value { get; set; }
}
[Table("ProductCodeTable")]
public class ProductCode : LookUpEntity
{
}
This way you can model the relationships also and later if you wanted to add specific properties to those look up entities with out affecting other entities.
You can create a view with a Union of all tables like this:
create view AllKeyTables as
SELECT 'Product' as table, Productkey as Key, nameProduct as name
FROM ProductCodeTable
UNION
SELECT 'Country' as table, CountryISO as key, CountryName as name
FROM CountrycodeTable
UNION
...
Then update EF model and check 'table' and 'key' fields as Entity Primary Key.
Next question you will do is: 'How can I make a relation between this Entity and existing Entities?' The answer is 'you can't because EF is not able to join Entities between other fields than primary key'. Then, before implement this solution, be sure that this is you are looking for.
EF supports this only if you model it as inheritance (#Eranga showed it in code-first approach). You will have single base entity and derived entity for each table so you will not avoid having different type for each table. Otherwise the answer is no.
Inheritance will put additional requirements on data in your tables. For example Ids will have to be unique among all tables. So if ProductTableCode will have record with Id 1, CountryCodeTable (and any other code table) mustn't have record with Id 1.
Also inheritance in EF can produce nasty and very poorly performing queries.
Hey, sorry for my bad english...
Using EF4 code-only, I have created some POCO classes and my database was generated from that. All worked fine, I inserted some data on the tables but now I need to create a new property on one of my classes. If i just create it, the application give me the exception:
{"The model backing the 'TestContext' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the RecreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data."}
I tried to create manually the field on the table, but it is still complaining... does someone know if there is a way and if so how can I manually update the database schema (i don't want to recreate it because i already have data) to match the model?
It should work if you make sure that your new column match exactly your new property.
For example, if you add a property NewProp
public class MyEntity
{
[Key]
public int Id;
public string PropA;
public int PropB;
public int NewProp;
}
then in your database table MyEntities, you would add a column NewProp of type int not null.
What you can do to check if the column you add is correct, is to rename your database, then let Code-First recreate the database and see what's different between the original and new databases.
EF generates partial classes. So you can add new properties(fields) in another partial class.