Entity Framework Core can't map official types to PostgreSQL columns - postgresql

I downloaded a sample database for Postgres (v14) (dvdrental) so I could follow some SQL tutorials. I wanted to create an ASP.NET Core (5) Web API for that database, so using scaffolding, I created the entities based on the database tables and columns, then after some minor changes, I wanted to create a new migration.
That step failed though, as I'm getting two errors (so far) regarding the data types.
The property 'Film.Fulltext' is of type 'NpgsqlTsVector' which is not supported by the current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'
I tried to use [NotMapped], but got the same error. I also tried to specify
[Column(Typename = "tsvector")]
which is the official type mapping according to https://www.npgsql.org/doc/types/basic.html, but for some reason, EF core seems to ignore it completely and gives the same error.
The property 'Film.SpecialFeatures' could not be mapped because it is of type 'string[]', which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'
Which is, again, weird, as the Postgres websites says
public string[] Tags { get; set; }
The provider will create text[] columns for the above property..
So basically EF Core throws errors about something that is the officially recommended way of doing it, so I have no idea why these errors even occur or how I could solve them.
Any help is appreciated.
Thanks

Related

EF core to support nvarchar

I have an existing EF code first project which has created the database with all nvarchar columns in the database. Now I am starting another project on the same database for statistical purpose. This new project however is using EF core as pointing to same database. When I tried to run the new project, it gives me following error.
"Data type 'VARCHAR' is not supported in this form. Either specify the length explicitly in the type name, for example as 'VARCHAR(16)', or remove the data type and use APIs such as HasMaxLength to allow EF choose the data type."
Now, as I already have production data in the database so I want to make minimum impact to the column types but still wan to use EC core in my new project. I have so many nvarchar columns so setting configuration on individual table is a hard job. Anyone can point me in the right direction?
This seems to be an issue with the 2.0 release of EntityFrameworkCore: https://github.com/aspnet/EntityFrameworkCore/issues/9188
Supposed to get fixed in 2.1 so you may want to wait until then.
Otherwise they suggest manually fixing it like this:
entity.Property(e => e.Comments)
.HasColumnName("Comments")
.HasColumnType("nvarchar(4000)"); // <- Add this
I'm using data annotation and it still works.
[Column(TypeName = "varchar(50)")]
I can confirm its been fixed on later version, not sure about 2.1 but it disappeared in 2.2 for sure.
https://github.com/aspnet/EntityFrameworkCore/issues/13609

FSharp Record Types With Entity Framework Code-First

I am doing a proof of concept in a line of business application where I want to swap out the current C# Code-First Entity Framework implementation with a F# one. I am following this article which seems to work pretty well, but I was hoping to use FSharp record types instead of the classes that the article uses. When I try and add a data annotation to a record type like this:
type Family = {[<Key>]Id:int; LastName:string; IsRegistered:bool}
I get the following error:
Error 1 The type 'Key' is not defined
Is there a way to use data annotations with record types? Apparently, EF Code-First needs annotations...
Record types support attributes just fine (and with the syntax you have).
Check if your reference to System.ComponentModel.DataAnnotations is in order, that's where KeyAttribute is defined.
Edit: EF wants to work with properties, that's why using a record doesn't mesh well with EF. You can still make it work in F# 3.0+ by marking the record with CLIMutable attribute (this generates property setters and a parameterless constructor which are taken for granted by C#-centric frameworks and libraries).
The article you're looking at was written with F# 2.0 in mind - CLIMutable wasn't around yet and there was no way of using records for that.

How to use PgSqlType with devart entity developer

I want to map the postgres type point to the Devart.Data.PostgreSql.PqSqlPoint structure.
I found a table (devart PgSqlTypes) in which is stated for point: "May be represented as the PgSqlPoint class or the Srting".
However in devart's Entity Developer I can only choose Dot.Net standard types like String,Byte,Int16,Int32,Boolean etc. for the generated entity's respective property and did not find a way to select Devart.Data.PostgreSql.PqSqlPoint as type.
Would this be possible somehow or will I allways have to do the conversions myself in the code of my property's getter?
Your help is much appreciated.
p.s. We are using Entity Framework as ORM framework.
Entity Framework supports only primitive types: http://msdn.microsoft.com/en-us/library/ee382832.aspx . From the Entity Framework's point of view, a PqSqlPoint is not a primitive type.
As a woraround, map the point column in the database to the string property in both CSDL and SSDL parts of your model.
Additionally, you can create a PqSqlPoint property (it will convert string to PqSqlPoint) in the partial class: http://www.devart.com/dotconnect/postgresql/docs/?Devart.Data.PostgreSql~Devart.Data.PostgreSql.PgSqlPoint~Parse.html . But it will be readonly.
We are going to support PostGIS in our Entity Framework implementation. Are you interested in this feature? If yes, we can send you our internal build before the release to take into account your remarks and suggestions in the final version.

Get Model schema to programmatically create database using a provider that doesn't support CreateDatabase

I'm using the SQLite provider for Entity Framework 5 but it doesn't support CreateDatabase and thus cannot auto create the database. (Code First)
Is there a way I can obtain the Model schema at runtime so that I can create the SQL "CREATE TABLE" command myself?
If not at runtime, some other way to obtain the schema so I know how to create the table properly?
Thanks!
A) As for obtaining the model schema at runtime part
(all are earlier posts of mine)
See this one How I can read EF DbContext metadata programmatically?
And How check by unit test that properties mark as computed in ORM model?
Also this one for a custom initializer Programmatic data transformation in EF5 Code First migration
Having said that...
The problem I see is where and at what point you actually have the data available.
Actually I'm quite sure you won't be able to do that at any time.
Because to be able to extract that info you need to have a DbContext running - so db has to be constructed etc. etc.
In the initializer maybe - but using different ways to get that info - the above is not available.
B)
The other way would be to go the way of implementing a provider, generator etc. (e.g. this post).
That way you should get all that info just at the right time from the EF/CF itself.
However I haven't played with that much.
For more info you can check the EF source code
This is more of a 'gathered info' so far - in case it helps you get anywhere with it. Not really a solution. I'll add some more tomorrow.
EDIT:
To get the real database metadata, look into the other DataSpace, this should get you to the right place...
(note: things tend to get less exact from here - as obviously there isn't the right official support)
var ssSpaceSet = objectContext.MetadataWorkspace.GetItems<EntityContainer>(DataSpace.SSpace).First()
.BaseEntitySets
.First(meta => meta.ElementType.Name == "YourTableName");
If you look up in debugger, Table property should have the real table name.
However, reflection might be required.
How I can read EF DbContext metadata programmatically?
How check by unit test that properties mark as computed in ORM model?
Programmatic data transformation in EF5 Code First migration
Entity Framework MigrationSqlGenerator for SQLite
http://entityframework.codeplex.com/
Entity Framework - Get Table name from the Entity
ef code first: get entity table name without dataannotations
Get Database Table Name from Entity Framework MetaData
http://www.codeproject.com/Articles/350135/Entity-Framework-Get-mapped-table-name-from-an-ent

Upgrading from Entity Framework 4 to 5 resulted in error

After upgrading to EF 5 I keep getting Validation failed for one or more entities. See 'EntityValidationErrors' property for more details' in a particular instance of my code.
It turns out I have a field that is a NVARCHAR nullable in the database and it marked has [Required] with Data annotation in a partial class. The field in question is set to null programmatically. This worked fine in EF4 as it was validated against the database model (NVARCHAR nullable).
I need to keep that field marked as [Required] because it also takes user inputs in other instances.
What are my options? Can I ignore that attribute/validation error right before SaveChanges()?
This is why it is strongly recommended that you use View models, rather than passing your entities directly to the view. Your view and data model have different requirements, and trying to use the same model with validation causes problems.
Instead, remove the required attribute from your data model and create a View model that has the required on it, then use something like AutoMapper to map between them.