Npgsql data type mapping of Character from Postgresql to .NET Core 2.0 - postgresql

In a PostgreSQL database I have a RFC column which is sort of a code to identify Enterprises and people in Mexico (for taxes purposes), code that I need to store in my database. The format of this 'code' it's like the next one:
AAAXXXXXXAXX -> where A's are letters and X's are numbers.
I want to store RFC column as primary key. As far as I've searched, Postgres Character data type is good for this, and I have the SQL query of it as pgAdmin4 generates:
rfc character(13) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT pk_empresas PRIMARY KEY (rfc)
But, inside Visual Studio using Package Manager Console and the next command:
Scaffold-DbContext "Host=localhost;Database=database;Username=pgadmin;Password=xxxx" Npgsql.EntityFrameworkCore.PostgreSQL -force
It generates my models that are mapped as the tables in my database.
The question here is, how can I work correctly if .NET char datatype only holds a single character and the property RFC is generated as follows?
public char Rfc { get; set; }
This first approach stores only the first character. I can see it in pgAdmin4
Database record saved
I've tried to change Rfc property data type(as I know that some .NET data types can match to others in PostgreSQL as we can see in the next link Npgsql Supported Types ) as string like this:
public string Rfc { get; set; }
But this Table is also related to another 4 or 5 Tables in my Database, and I get too many errors when I try to change the data type of this property in my model (as it is also related in models).
I have to say that I have tried this but it throws an exception.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries.
Edit 1:
I'm using Npgsql.EntityFrameworkCore.PostgreSQL version 2.0.1

This has been fixed for version 2.0.2 of the Npgsql EF Core provider which will be released very soon.
See https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/370 for the github issue.

Related

EF code-first migration: SqlCeException altering NTEXT column

My application uses Entity Framework 5.0 code-first on top of a Sql CE database. Until now, we have used Automatic Migrations to manage entity mapping changes. However, I now have a change for which I need to create a custom migration to ensure no data is lost during the update. I made my changes to the entities, and used the Add-Migration command which generated Up() and Down() methods for me. I customized the Up() method to insert my custom sql to preserve the data, and tested my application.
When I run the application, I received the error:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
Ok, I don't understand this because all of my changes are detailed in the Up() method that got executed.
So I turn Automatic Migrations back on just to see what happens. Now I receive this error:
"Cannot alter column of type NTEXT or IMAGE [ Column Name = LastName ]"
This error comes from a table/entity that hasn't even been touched with my changes. The existing database has this string mapped to nvarchar(4000). If I examine the DB after I receive this exception, I observe that the columns have been changed to ntext. What is EF doing? Why is it touching tables that haven't been changed? How can I get more information on what is going on here?
Update:
As a workaround, I attempted to mark each and every string type in my entities with a data annotation as such:
[Column(TypeName = "ntext")]
public virtual string LastName
{
get;
set;
}
Now all of my strings are using ntext in the database. This leads to further exceptions when queries are performed:
The ntext and image data types cannot be used in WHERE, HAVING, GROUP BY, ON, or IN clauses, except when these data types are used with the LIKE or IS NULL predicates.
So, to summarize:
Turning off automatic migrations causes EF to detect phantom changes and throw exceptions
Turning on automatic migration in conjunction with a custom migration causes all existing strings to be mapped to ntext
strings mapped to ntext cannot be queried, effectively making them useless in my application
For me, a modification of an Up method worked out.
SerialNumber = c.String(maxLength: 99)
was applied instead of
SerialNumber = c.String()
i had the same issue and i fixed by editing the table column data type manually by opening SQl Server Compact/SQlite Toolbox explorer windows, and then expend the database name, then expend the table you want to edit and right click the column you want to edit, and click drop script, then run the scrip and the column will be dropped from the table, then right click the table and click add column and from here you can choose what data type you want and add the new column that way. I hope this helps some one.

Slow linq query when looking for char(1) datatype using contains

I've got an old database with a char(1) Status column. I'm using code first and entity framework 4.3.1 to interact with my database. My Status column in my code first class is defined as follows:
[Column(TypeName = "char")]
public string Status { get; set; }
I'm writing a linq query to fetch all items with a Status of one of several values. The code looks something like this (although it's been simplified):
List<string> statusList = new List<string>() {"N","H","P"};
...
var entries = (from t in context.MyTable where statusList.Conains(t.Status)).ToList();
...
The SQL thats generated prefixes all the Status values with N making the query quite slow.
WHERE ([Extent1].[Status] IN (N'N', N'P', N'P'))
It seems to be because it's comparing unicode with non unicode so it can't use the index on the Status column.
I've had similar problems before in other linq queries, but I thought they were solved by putting [Column(TypeName = "char")] on the property.
Does anyone know how I prevent SQL from putting those N's in front of all my Status values? I tried making statusList a List of char, but then I needed to change the definition of the Status column to char in code first, but that threw errors.
Thanks
David
Are you on .NET Framework 4? I think this was fixed in EF5 core libraries shipped with .NET Framework 4.5. Here is a connect bug for this: http://connect.microsoft.com/VisualStudio/feedback/details/709906/entity-framework-linq-provider-defaulting-to-unicode-when-translating-string-contains-to-like-clause The connect bug also contains a workaround - use EntityFunctions.AsNonUnicode() function to force strings not to be Unicode which may be helpful if you can't move to .NET Framework 4.5

ODAC 11.2 Rel. 4 table and field names casing and numbers issues in EF 4.1

Just migrated ODP.NET 11.2 Release 4 from Devart DotConnect for Oracle http://www.devart.com/dotconnect/oracle/ but I got so many issues.
Number(1,0) data type must be translated as bool instead of Int16 or
short. Devart translated it correctly. I solved the issue by adding
<add name="bool" value="edmmapping number(1,0)"/>
Number(9,2) is translated as Decimal while it should be double. Devart translate it
double and this is correct. We need double datatype for this. Table
names are not adjusted if transformed as C# Class. For example I
have table "PRODUCTS" EF made a class "PRODUCTS" also with the same
casing. Devart on the other hand created "Products" which is exactly
the correct naming translation.
Field names are not adjusted if transformed as C# Class properties. For example table "PRODUCTS" has field PRODUCT_NAME it should be ProductName if translated into C#
Class property. Devart does it correctly.
Table Names and Classnames should be in Proper Case if translated to C#.
Underscores for table names should be removed.
For the bool mapping issue, you can find my solution here:
https://forums.oracle.com/forums/message.jspa?messageID=10402873#10402873
For the double mapping issue, there seem to be no solutions so far: https://forums.oracle.com/forums/message.jspa?messageID=10402783#10402783
Regarding the names transformation issue, Microsoft's provider for MSSQL doesn't do that automatically either.
You can rename everything manually, however, that is very annoying to do.
(Good to know that Devart can do that automatically.)

Entity Framework & SQL Compact Edition - how do I get ntext?

The answer to my question should be quite obvious, but I cannot find it. I have a edmx file that has one table. There is a field of type string. EF always generates nvarchar for that (which is kind of expected), but I need an ntext instead of nvarchar for that field as 4000 is too small for me.
So tell me - what is the proper way to tell EF to generate ntext fields?
PS Using Entity Framework 4, SQL CE 3.5
I guess you are using model first, don't you? You can simply create custom T4 template for SQL DDL generation and include logic which will use NTEXT when field is defined with max size.
Default template is on:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
Just copy this template and find the logic where data type is created. Once you have your template change DDL Generation Template in model properties (in the designer) to your modified version.
There is much more you can do with generation template because you can add some annotations to your model (XML) and use them for custom logic in the SQL generation process.
Just set the property "MaxLength" in the Designer to "Max". This will generate a ntext field in the SQL CE DB.
If your project contains an ADO.Net Entity Data Model (.edmx) then see Ladislav's excellent answer.
But if you're using the Code First libraries and your project doesn't contain a .edmx then you can use the System.ComponentModel.DataAnnotations.ColumnAttribute to specify the column type:
using System.ComponentModel.DataAnnotations;
public class Note {
[Column("Note", TypeName="ntext")]
public string Note { get; set; }
}

Entity Framework - Mapping decimal(13,0) problem

I'm migrating the aplication of my company (that nowadays run over SQL Server and Oracle) to ASP NET MVC and Entity Framework for persistence.
A create my Entity Model based on SQL Server Database e separately I create a SSDL for Oracle (for Oracle I use DevArt dotConnect for Oracle Provider) and I get some pain troubles.
My table primary keys are on SQL Server are of type decimal(13,0) and on Oracle are number(13,0) but Oracle map it's type to Int64 and SQL Server to decimal, but I need that SQL Server map it to Int64.
I make these modification manually on Entity Data Model and for create records it's works fine, but when I have to delete or update some record I got these error:
The specified value is not an instance of type 'Edm.Decimal'
Parameter name: value
at System.Data.Common.CommandTrees.DbConstantExpression..ctor(DbCommandTree commandTree, Object value, TypeUsage constantType)
at System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateValueExpression(DbCommandTree commandTree, EdmProperty property, PropagatorResult value)
at System.Data.Mapping.Update.Internal.UpdateCompiler.GenerateEqualityExpression(DbModificationCommandTree commandTree, EdmProperty property, PropagatorResult value)
at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildPredicate(DbModificationCommandTree commandTree, PropagatorResult referenceRow, PropagatorResult current, TableChangeProcessor processor, Boolean& rowMustBeTouched)
at System.Data.Mapping.Update.Internal.UpdateCompiler.BuildDeleteCommand(PropagatorResult oldRow, TableChangeProcessor processor)
at System.Data.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)
Someone can help me?
Why Entity Framework mapping are so fixed? It could be more flexible?
Ps.: The error that I got, I suspect that is because of a association.
I have a Entity named Province and another named Country and I think that the association between these Entities are causing the problem at update and delete.
Regards,
Douglas Aguiar
This may or may not help you, but i had the same error from doing this same thing. So I edited the Conceptual model and change the primary key field from Int32 to Decimal. So far, seems to have fixed things. I still need to test again against Sql Server and make sure this didnt break it.
I was getting the error "The specified value is not an instance of type 'Edm.Decimal' Parameter name: value" as you posted in your question. I had changed the default data types from Decimal to Int32 as this better reflects the true typing. When I first hit this error I rolled back the type changes and was still getting an exception but it changed just slightly but led to further digging. Bottom line, in my scenario we were expecting a trigger to populate the PK during persistence via Before Insert directive. The problem was that the domain class built by EF was setting the PK at 0 so the trigger was never firing as the incoming PK was not null. Of course EF will not let you set the Entity PK to be nullable. Maybe this will help someone else in the future.