EF Core Unique constraints with "NULL" values - entity-framework

The solution of Does EF Core allow a unique column to contain multiple nulls? works perfect with
Microsoft SQL Server but not with PostgreSQL. Is there a solution which works also with PostgreSQL (Npgsql provider) ?

You can simply use a filtered index to specify the WHERE clauses as you wish:
modelBuilder.Entity<Blog>().HasIndex(b => b.SomeInt)
.HasFilter(#"""SomeInt"" IS NOT NULL")
.IsUnique();
This creates the index as follows:
CREATE UNIQUE INDEX "IX_Blogs_SomeInt" ON "Blogs" ("SomeInt") WHERE "SomeInt" IS NOT NULL;

Related

EntityFramework PostgreSQL GIST index for geography column

I'm trying to create a index, like this one:
CREATE INDEX example1_gpx ON example1 USING GIST (geography(geomcol));
Using EF codefirst, I did this on codefirst:
builder.HasIndex(x => new
{
x.GeoLocation
})
.HasMethod("GIST");
but I can't specify that it's a column of type geography.
How I can create this index using CodeFirst ?
Your index above seems to apply a geography() conversion to a geometry column; if so, it's an expression index (as opposed to a simple index over a column). The Npgsql EF Core provider doesn't currently support modeling expression indexes (see this issue), but you can always use raw SQL to create the index in migrations.
However, I'd recommend thinking why you're converting a geometry column into geography in an expression index; you may want to consider making your column geography instead. Another option is to have an additional generated column of type geography alongside the geometry column.

Adding a primary key into an existing table using Entity Framework Core

I have an existing, populated table. Using an EF Core migration, I want to create a DB Generated Primary Key.
Here's my fluent API:
modelBuilder.Entity<MyTable>()
.HasKey(a => a.Id);
modelBuilder.Entity<MyTable>()
.Property(p => p.Id)
.ValueGeneratedOnAdd();
The issue that I have is that, when I run migration, I get an error, because the existing rows in the table do not have this (new) field populated:
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'dbo.MyTable' and the index name 'PK_MyTable'. The duplicate key value is ().
Is there a way that I can leverage the default value to retrospectively populate this table with primary keys? Alternatively, is there another way to populate this field retrospectively?
Alternatively, is there another way to populate this field retrospectively?
Yes. But not through EF. You'll need to clean up the database manually before EF can start managing the schema.

How to annotate unique constraint with WHERE clause in JPA

I need to use these unique constraints in PostgreSQL
CREATE UNIQUE INDEX favorites_3col_uni_idx
ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favorites_2col_uni_idx
ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
The first one I annotate in JPA:
#Table(uniqueConstraints= {
#UniqueConstraint(name="favorites_3col_uni_idx", columnNames = {"user_id", "menu_id", "recipe_id"})
})
But, ¿it is possible to annotate in JPA the second unique index?
Thx.
You appear to want to create partial indexes (CREATE INDEX ... ON ... WHERE) using JPA constraint definitions.
These are fairly PostgreSQL specific, and aren't specified by JPA. You will need to use native syntax to create them. I don't believe JPA offers any features for index definition.
You cannot use a unique constraint for this purpose because unique partial indexes are not unique constraints. Partial unique indexes cannot be created with CONSTRAINT constraint_name UNIQUE(columns) in PostgreSQL. It's only an implementation detail that PostgreSQL creates a unique index for a unique constraint at all.
See:
Specifying an Index (Non-Unique Key) Using JPA
JPA: defining an index column
Some JPA providers offer extension annotations specific to that JPA provider that add features for running native DDL scripts, defining indexes with annoations, etc. Since you haven't mentioned which JPA provider you are using I can't tell you more. Here's the documentation for EclipseLink index DDL; this will not work if you are using Hibernate, OpenJPA, or something other than EclipseLink.
A JPA standard workaround is to check for the presence of those indexes during startup by querying pg_catalog.pg_index. If you don't find them, use an EntityManager native query to send the appropriate native SQL CREATE UNIQUE INDEX commands. A #Startup #Singleton bean is useful for this sort of task if you're using EJB3.1. See the PostgreSQL documentation for the structure of pg_catalog.pg_index. To just check if an index of a given name exists, run:
SELECT EXISTS(
SELECT 1
FROM pg_index
WHERE indexrelid = 'public.indexname'::regclass
);
Note that the above query does nothing to verify it's the index you expect, but you can do that with some additional checks. Just examine the contents of pg_index after creating the index so you know what to test for. I don't recommend trying to check for any particular value of indpred; just make sure it isn't null.

DB2 Character Datatype and JPA Not Working

I am working with DB2 Universal database having lots of tables with columns of datatype CHARACTER. Length of these columns is variable (greater than 1 e.g. 18). As i execute a Native query using JPA it selects only first character of the column. Seems CHARACTER datatype is mapped to Java Character.
How can i get full contents in DB column. I can not change the database bening on Vendor side. Please note i need to do it both ways, i.e. :
Using JPQL ( is attribute columnDefinition can work in this case)
Using native DB query (no pojo is used in this case and i have no control over datatypes)
i am using Hibernate implementation of JPA provided by spring.
If these columns are actually common in your database, you can customize a dialect used by Hibernate. See comments to HHH-2304.
I was able to cast the column to VARCHAR to produce padded String results from createNativeQuery:
select VARCHAR(char_col) from schema.tablename where id=:id

How do I *not* supply a column for update in EF?

I am sure I am not the first one to struggle with this.
I am using Entity Framework 1 (VS2008) and one of the columns in the table is ModifiedDate. It has DefaultValue in SQL Server (getdate()); so I would like to leave it the DB to do the generation. However, generated SQL has INSERT (... ModifiedDate) VALUES (... null), and the default value doesn't get inserted.
Is it possible to not specify this column at all?
By setting StoreGeneratedPattern in SSDL.