I have a problem with conditional compiling in EF Core on .NET 8 as described later. It seems as if EF Core code generates SQL that does not take project defines in account.
I know how to make a brute workaround by commenting the offending line but it is, well, pain in the... I will really appreciate if someone can confirm my findings. I will be thrilled if someone has a more elegant solution.
Just a short background why this is important to me: in my reality, AlternateId
is part of a base class bunch of entities are derived from a complex database server app. I tried to use same source files (using file linking) instead of copying nearly the whole project's code to MAUI project and disable the only single attribute that makes thing incompatible.
I have quite unusual code in EF Core with the entity defined as
public class MyEntity
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
#if !PROJECT_TABLET
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
#else
[DatabaseGenerated(DatabaseGeneratedOption.None)]
#endif
public int AlternateId { get; set; }
}
I am using this file in a Blazor server application with SQL Server, and in MAUI tablet application (using SQLite), the latter with PROJECT_TABLET
defined in project options.
On server side in SQL Server, everything works as expected, SQL Server will compute and use AlternateId
as expected.
In MAUI application (using SQLite and with PROJECT_TABLET
defined) everything looks fine until I run the app. That is, the SQLite database is properly created (eg no index is created on AlternateId
). But if I run any code that will insert the SQL code generated by EF core is
INSERT INTO "Entities" ("Id","Name")
VALUES (@p0, @p1)
RETURNING "AlternateId";
And this results in an exception
SqliteException: SQLite Error 19: 'NOT NULL constraint failed'
on the AlternateId
. To make sure, my test code was
#if !PROJECT_TABLET
This is not code and will generate compile time error;
#endif
MyEntity entity = new MyEntity{ Id = 101, Name = "Test", AltrenateId = 1001 };
_context.Entites.Add(entity);
_context.SaveChanges(); // <- error happens here
Note that the MAUI application works as expected as soon as I comment out
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
or change it to
[DatabaseGenerated(DatabaseGeneratedOption.None)]
It seems like
#define
and takes [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
when generating SQL code in the MAUI program#define
and generates proper output.Can someone please confirm my findings? Do you have some idea on workaround or how to make it work, where to report?
Regards
Goran
Ok, this report will go into "The Twilgiht Zone" category.
@David Browne - microsoft and @Steve Py, your comments were enough to make me dug further.
As you suggested this wouldn't be an EF issue I rechecked my code. I found out that in MAUI project I defined PROJECT_TABLET for android target only, but I run code on Windows target. Therefore, the code was properly compiled against DatabaseGeneratedOption.Computed.
Clean and recompile after fix and the problem is solved, as expected.
Still, it made we wonder why I didn't get compile-time error in the line
#if !PROJECT_TABLET
This is not code and will generate compile time error.
#endif
But I can't reproduce this behavior. I tend to triple check my code before posting and I'm 100% sure that I copied SQL code generated while test code above included. Either my memory crashed miserably or I felt in VS2022/MAUI hole with clean-delete-close reboot. I'll never know...