5

I have added new property in my Entity Model as the new column has got added in DB table. But In that column might or might be there in other client database. So, How handle this? I have tried modelBuilder.Entity<Customer>().Ignore(customer => customer.FullName); But it's not ignoring the property in entity. Because we have entity mapped class so it is not ignoring it. Solution please?

Sherlock
  • 499
  • 1
  • 7
  • 18
  • 1
    That will remove the mapping if you add a migration. – Aluan Haddad Oct 08 '20 at 13:32
  • 1
    Sorry, but the Context has to match the database structure. If it doesn't, than you can't use that context. – Oliver Oct 08 '20 at 14:37
  • Hey, I did some research and it seems like internally within entity framework the Ignore function adds a value to a hashset which is used in a class called TypeMapper [link](https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.core.mapping.typemapping?view=entity-framework-6.2.0). I presume this class is responsible for mapping your cs classes to database tables. I have no idea it this is possible but maybe overriding this class or defining an IgnoreIfNotPresent() function could set you on the right direction here (seems like a complex task though) – Jochem Van Hespen Oct 12 '20 at 10:28
  • Why add the column to the same table. We have some dynamic fields in a separate table. They are mapped to the key of the main table and have a field name and a string value. Be carefull though! This concept works fine for not too large amounts of data. If you have really large datasets and want to query all of them this would become a performance drain. – Paul Sinnema Oct 12 '20 at 20:49

2 Answers2

3

If you add the [NotMapped] attribute, entity framework will not create a column for it.

using System.ComponentModel.DataAnnotations.Schema;

namespace DomainModel
{
    public partial class Customer
    {
        public int Id { get; set; }

        public string Name { get; set; }

        [NotMapped]
        public string FullName { get; set; }
    }
}

Or if you want to map the column, but in some databases it already exists, here's a migration which will add the column only if it does not exist.

namespace DataAccess.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddFullNameToCustomer : DbMigration
    {
        public override void Up()
        {
            Sql(@"IF COL_LENGTH('Customer', 'FullName') IS NULL
            BEGIN
                ALTER TABLE Customer
                ADD [FullName] varchar(200) null
            END");
        }
        
        public override void Down()
        {
        }
    }
}
Albert
  • 91
  • 1
  • 4
  • Changed my answer – Albert Oct 08 '20 at 15:07
  • You can only map it if it exists, and if it does not exist, you have to create it with a migration. So my previous answer was the thing you needed, really, i'll revert back to my previous answer. With that, if some of your clients don't have that column, it will be added when they launch the program. If some of your clients do have the column, it will use that. – Albert Oct 09 '20 at 07:10
  • I think a migration is really needed, so you need to update all your client applications, otherwise they will get an error like "the context does not match the database". I don't have an other solution for you, maybe someone else. – Albert Oct 09 '20 at 08:30
  • If you have one database with multiple instances of your application, all instances need to be updated. If you have multiple applications with each their own database, you can add the migration and update only the one application which needs the new column. – Albert Oct 09 '20 at 08:40
1

Just stop it. You're creating a world of pain for yourself.

If you want to have a dynamic schema, then you shouldn't be using Entity Framework at all.

Simplify and avoid all this headache by creating a migration that ensures that the field gets created in every single database (so that at runtime, the context will always match the database) and make sure the migration is executed before the app runs.

C. Augusto Proiete
  • 24,684
  • 2
  • 63
  • 91