Entity Framework "Invalid Column Name" - entity-framework

We have converted an existing DB to use EF, so we write classes to map to our tables. I've added a new column, a nullable int called 'iframeVideoId'. I mapped it with
public int? iframeVideoId { get; set; }
and when I do a search of that table, it blows up with an '
invalid column name' error
. This is a simple property it's not an index or related to any other table. I tried renaming it in the DB to 'DisplayVideo', and also making it not nullable. Then I had
[Column("DisplayVideo")]
public int iframeVideoId { get; set; }
Now I get an error that DisplayVideo is not a valid column. Of course I have double checked that I am pointing to the right DB, and confirmed that every DB that my code COULD point to, has this column. I've also done a clean and rebuild all, and rebooted my machine. What could be wrong ? This is a basic column, and it's there. I know from past experience that if the types did not match ( they are both int ), I'd get an error related to failed conversion between types. This makes no sense to me at all. I do not have an edmx file to refresh, because we're writing classes to map to the DB directly
Just to add, I changed the column to a string and it makes no difference. This is a new column, with a simple value, and EF claims it's not there.
And, I added the column to another table ( suboptimal, obviously ) and it just plain worked, immediately. I'd still like to know why I have a table I can't add columns to in EF, though

I had an error in my mapping class from copy/paste situation. As you can see, mapped TranferredToEVP to 3 different columns. I was getting an "invalid column name" on the last column TranferredToGUID but was looking for TranferredToGUID1. Hope this helps.
this.Property(t => t.TransferredToEVP).HasColumnName("TransferredToEVP");
this.Property(t => t.TransferredToEVP).HasColumnName("TransferredToName");
this.Property(t => t.TransferredToEVP).HasColumnName("TransferredToGUID");

I had the same issue like Amy Jonas had, if you happen to come across this, make sure the mapping is correct.
My code looked like this before :
Property(d => d.LastUpdatedOn).HasColumnName("LastUpdatedOn");
Property(d => d.LastUpdatedOn).HasColumnName("LastUpdatedBy");
It should be :
Property(d => d.LastUpdatedOn).HasColumnName("LastUpdatedOn");
Property(d => d.LastUpdatedBy).HasColumnName("LastUpdatedBy");
Sometimes we get too busy that we forget to look at these details.

Related

EFCore Map 2 entities to same table

I'm trying to use DDD with EFCore and I am struggling to find a way to map 2 POCOs from different context that represent the same entity to the same table.
I have a User class inside UserContext, with all the properties needed to create a new user to my application.
And I have either a User class inside my OrderContext, in this class I only have the Id and Email properties, cause it's all that is needed in OrderContext to work.
So I have something like this:
modelBuilder.Entity<Domain.UserContext.User>(u =>
{
u.ToTable("User").HasKey(e => e.Id);
u.OwnsOne(e => e.Name);
u.OwnsOne(b => b.HomeAddress);
});
modelBuilder.Entity<Domain.OrderContext.User>(u =>
{
u.ToTable("User").HasKey(e => e.Id);
});
modelBuilder.Entity<Domain.OrderContext.Order>(p =>
{
p.ToTable("Order").HasKey(b => b.Id);
p.HasOne(x => x.User); // this is OrderContext.User
});
I can't seem to find a way to map both User classes to the same table. Is there a way to do it?
Edit1: Both contexts are bounded context DDD's concept not DbContext.
I just need both classes to be maped as the same table. The Add-Migration command return a message telling me that it cannot map 'OrderContext.User' to table 'User' since it is already mapped to 'UserContext.User'.
The main cause of issue is, EF Core cannot figure out how to use same table for 2 different entities. There is lack of data in mapping, once you fill that in, it works as expected.
First you will need to define how are they related to each other. Sharing same table with same PK does not have Foreign Key defined on server side but there is still intrinsic relationship between both entities which is one-to-one and using PK as FK. Once you define relationship, you will see that it works and both entities are mapped to same table. (Just like how owned entities are mapped to same table). This may not be end of mapping for your case though. Since from EF perspective they are still 2 different entities, except for Id (or PK property), they will have own columns to store data. But what if you have columns which are common in both the context (like Email in your scenario). In such case, you would need to provide mapping for those additional column too. If you map them to same column explicitly, they will start sharing the column in database. Overall the code would look like this.
namespace UserContext
{
public class User
{
public int Id { get; set; }
public string Email { get; set; }
// Other properties
}
}
namespace OrderContext
{
public class User
{
public int Id { get; set; }
public string Email { get; set; }
}
}
// In OnModelCreating method
modelBuilder.Entity<UserContext.User>(u =>
{
u.ToTable("User");
u.Property(e => e.Email).HasColumnName("Email");
// Configuration for other properties
});
modelBuilder.Entity<OrderContext.User>(u =>
{
u.ToTable("User");
u.Property(e => e.Email).HasColumnName("Email");
u.HasOne<UserContext.User>().WithOne().HasForeignKey<OrderContext.User>(e => e.Id);
});
Above code creates single table with shared columns and should work as expected. You can add more entities in the same table if you want by following same configuration. Here, I used User from UserContext as principal side but you can use any side. The main reasoning for me was, UserContext.User will be the entity which will be added when adding new User. Entities sharing the table do not have to be subset either. But there will be columns for additional properties which are not shared.
#Smit provided solution should work, but it is not ideal for isolated bounded contexts, where each of them is not aware of one another and each is taking care of it's own configurations.
I have solved this problem by adding separate DbContexts for each bounded context. Each of these contexts inherit base DbContext, where I have my shared logic (like auditing, etc.), and each DbContext inside bounded contexts has it's own DbSets and Fluent Api configurations. This way I have entities which point to the same table, but from different DbContexts.
I am looking at this problem myself. I noticed, that if you specify schema name for one of the tables then EF will not complain.
For example in your case:
modelBuilder.Entity<Domain.UserContext.User>(u =>
{
u.ToTable("User", "dbo").HasKey(e => e.Id);
u.OwnsOne(e => e.Name);
u.OwnsOne(b => b.HomeAddress);
});
modelBuilder.Entity<Domain.OrderContext.User>(u =>
{
u.ToTable("User").HasKey(e => e.Id);
});
Of course this is not a full solution and even not a workaround, since you can not have more than 2 mentions of "User" table (that is, in more than 2 contexts).
Also i found https://data.uservoice.com/forums/72025-entity-framework-core-feature-suggestions/suggestions/1872001-map-multiple-entities-to-same-table which makes me think that this in general is not possible.
Regarding DDD in general
Most sources say that your bounded contexts should be isolated not only by code, but also by data. This in theory means, that your User table should be duplicated in each bounded context. This is ideal way, but is unnecessarily complex (imho) for more simple scenarios, since it involves data synchronization across all duplicated tables.

Why does Entity Framework insist on renaming columns?

Step 1: import code first from existing database. Existing database has a table with the same name as column.
Step 2: in this scenario, Entity Framework sticks a "1" in front of column name in code.
Step 3: when I try to rename it "by getting rid of 1 in front", I get error
member names cannot be the same as their enclosing type
Why is this limitation on EF and is there a solution that doesn't ruin the database in future migrations (by having that column renamed)?
Being forced to use Column1 just seems really terrible and arbitrary.
Thanks.
As pointed out by #shf301 you cant have a property named the same as the class its in, this is a .NET restriction.
However you can name your column anything else and then tell EF to point to your specific column in the database
eg:
[Column("MyColumn")] // "MyColumn" will be what EF expects in the db
public int FlyingMonkies {get;set;}

Table Splitting / Optional Relationship

Currently, I have the following in my code:
modelBuilder.Entity<Client>().HasRequired(e => e.Logo).WithRequiredPrincipal();
This relationship definition is used for table splitting the Logo column (which is VARBINARY(MAX)) into a separate entity. Everything works as expected.
I have chosen to make the Logo column nullable in the database. I tried updating the code listed above to:
modelBuilder.Entity<Client>().HasOptional(e => e.Logo).WithOptionalPrincipal();
When I run the code, I receive the following message:
Additional information: The entity types 'ClientLogo' and 'Client' cannot share table 'clients' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.
The problem is that I am not entirely sure what this message is trying to tell me. Why does it work when the Logo column is non-nullable but does not work when it is not? Am I mapping the relationship incorrectly?
Even if the Logo column is optional, the entity relationship between ClientLogo and Client needs to remain the same, it's the property itself that needs to be nullable:
// This should stay the same
modelBuilder.Entity<Client>().HasRequired(e => e.Logo).WithRequiredPrincipal();
// If you used to have a line like this or a [Required] attribute, then it needs to be removed
// modelBuilder.Entity<ClientLogo>().Property(t => t.Logo).IsRequired();

How to alter relationship keeping existing data in entity framework code first?

I have two entities
public class Account
{
[Key]
public int Id { get; set;
public int MemberInfoId { get; set; }
public Member MemberInfo { get; set; }
//Other Properties
}
public class Member
{
[Key]
public int Id { get; set; }
//Other Properties
}
With following relationship
modelBuilder.Entity<Account>()
.HasRequired(a => a.MemberInfo)
.WithMany()
.HasForeignKey(a => a.MemberInfoId)
.WillCascadeOnDelete(true);
However, an Account has one Member only so the following relation is better suited (I guess)
modelBuilder.Entity<Account>()
.HasRequired(a => a.MemberInfo)
.WithRequiredPrincipal()
.WillCascadeOnDelete(true);
But code first migration won’t migrate to that. It gives the following error
The object 'PK_dbo.Members' is dependent on column 'Id'.
The object 'FK_dbo.Accounts_dbo.Members_MemberInfo_Id' is dependent on column 'Id'.
ALTER TABLE DROP COLUMN Id failed because one or more objects access this column.
What can I do to alter the relation without recreating the database to keep the already inserted data?
First, you can read this page on mixing code-based migrations with automatic migrations to see if you even want to go this route in the first place. Generally, it's not a good idea if you have a team involved.
Next, it might be good to know that if you change the relationship between Member and Account to a one-to-one, Entity Framework requires that the primary key on the dependent side also be the foreign key. The column that used to be the primary key on the dependent side will become useless from EF's perspective. You also won't need the Account.MemberInfoId anymore, either.
Finally to create a migration, after you finish modifying the models, you can run Add-Migration with a migration name. This will create a migration file with a DbMigration class that you can modify. You'll probably need to do something like the following:
Create a new column in Member that will hold the new foreign key
Use Sql() to update values in that column with the primary key of the associated account
Drop the foreign key constraint, index, and primary key
Drop the account.memberinfo_id column and member.id column (which is optional, but if you don't drop the member.id column, you'll have to make sure to map the model's Member.Id property to the column created above).
Rename new column in member to id
Add primary key to new column in Member
Add index and foreign key
I'm sure I've missed something, but that's the general gist. I'd probably also backup everything, since something's guaranteed to go wrong the first five times or so.

Change Table and Column Name Mappings Entity Framework v4.3

I've got an application with a working Entity model generated from an existing database. I have to point my application at a new database, with the same schema, except that the table and column names are different.
For example, my current schema has tables named like "Answer". My new schema that I need to point to has the exact same table, except it is named "tblAnswer".
My columns have also changed. Where as a column used to be called "AnswerId", it's now "zAnswerId". Don't ask about the "z" prefix, it's a long story, but it's on every column.
So, what options do I have to point this existing Entity Model (generated from the database) to a new database and adjust the mappings? I've been experimenting with some of the techniques that are used for "Code First" mappings, as outlined in this guide, but haven't had any luck. I simply don't know if this is the right approach, or if there is something that makes more sense.
Suggestions? Thanks in advance.
You can change the database in the web.config file.
Use data annotations to use the different table and column names.
For example:
[Table("tblAnswer")]
class Answer
{
[Column("zAnswerId")]
public int AnswerId { get; set; }
}