Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case insensitive name of tables and properties in Entity Framework 7

I use Entity Framework 7 with Npgsql adapter. Sql generated by EF seems like

SELECT "r"."Id", "r"."Name" FROM "public"."Role" AS "r"

and it doesn't work in Postgres, because case-sensitive policy. To make it work i need to write create table script

CREATE TABLE "Role" (
    "Id" int,
    "Name" varchar(200)
);

But it's ugly. Is there the way to make EF generate scripts without quotes or with lowercase naming style?

like image 338
user3272018 Avatar asked Mar 10 '16 10:03

user3272018


People also ask

Is values stored in a table are case insensitive?

This means database and table names are not case sensitive in Windows, and case sensitive in most varieties of Unix. One notable exception is Mac OS X, which is Unix-based but uses a default file system type (HFS+) that is not case sensitive.

Is SQL_Latin1_General_CP1_CI_AS case sensitive?

Database collation For example, the default server-level collation in SQL Server for the "English (United States)" machine locale is SQL_Latin1_General_CP1_CI_AS , which is a case-insensitive, accent-sensitive collation.

Are table names in Postgres case sensitive?

So, yes, PostgreSQL column names are case-sensitive (when double-quoted): SELECT * FROM persons WHERE "first_Name" = 'xyz'; Read the manual on identifiers here. My standing advice is to use legal, lower-case names exclusively so double-quoting is not needed.

How do you make a LINQ query case insensitive?

Use string. Equals(name, article.Name, StringComparison. OrdinalIgnoreCase) when you are sure that your database supports it. E.g. SQLite with a collate of NOCASE will ignore the option.


2 Answers

  1. Override DelimitIdentifier in NpgsqlSqlGenerationHelper like this:

    public class SqlGenerationHelper : NpgsqlSqlGenerationHelper
    {
        public override string DelimitIdentifier(string identifier) => identifier.Contains(".") ? base.DelimitIdentifier(identifier) : identifier;
    }
    
  2. Replace ISqlGenerationHelper with your class using ReplaceService method:

    public class MyContext : DbContext
    {
        public virtual DbSet<MyTable> MyTable { get; set; }
    
        public MyContext(DbConnection connection) :
               base(new DbContextOptionsBuilder().UseNpgsql(connection)
                                                 .ReplaceService<ISqlGenerationHelper, SqlGenerationHelper>()
                                                 .Options) 
        { }
    }
    
like image 187
Maksim Fedorov Avatar answered Sep 18 '22 13:09

Maksim Fedorov


Here's a compact solution for .NET Core 3.X - Net5 (might well work in Net6). This will assume all tables and columns are in lowercase and quoted. You'll find that unconditional quoting helpful if someone names a table/column conflicting with a reserved keyword (e.g.: "user", "role", "default", "comment" etc).

    /// <summary>A replacement for <see cref="NpgsqlSqlGenerationHelper"/>
    /// to convert PascalCaseCsharpyIdentifiers to alllowercasenames.
    /// So table and column names with no embedded punctuation
    /// get generated with no quotes or delimiters.</summary>
    public class NpgsqlSqlGenerationLowercasingHelper : NpgsqlSqlGenerationHelper
    {
        //Don't lowercase ef's migration table
        const string dontAlter="__EFMigrationsHistory";
        static string Customize(string input) => input==dontAlter? input : input.ToLower();
        public NpgsqlSqlGenerationLowercasingHelper(RelationalSqlGenerationHelperDependencies dependencies) 
            : base(dependencies) { }
        public override string DelimitIdentifier(string identifier)
            => base.DelimitIdentifier(Customize(identifier));
        public override void DelimitIdentifier(StringBuilder builder, string identifier)
            => base.DelimitIdentifier(builder, Customize(identifier));
    }

Plugging it in is straightforward enough:

optionsBuilder.UseNpgsql(...)
  .ReplaceService<ISqlGenerationHelper, NpgsqlSqlGenerationLowercasingHelper >();

like image 34
nachonachoman Avatar answered Sep 16 '22 13:09

nachonachoman