Open wonea opened 7 years ago
Hello @wonea ,
This is currently due to some limitation of EF Core not handling cast yet correctly in LINQ.
See the limitation section:
Entity Framework Core:
There is currently a workaround with enabling ForceCast ( I will add this section to the Wiki) See the comment here: https://github.com/zzzprojects/EntityFramework-Plus/issues/74#issuecomment-258886038
We added the text to the Wiki : Entity Framework Core - Limitations
Let me know if everything is clear.
Best Regards,
Jonathan
Thanks for your reply, and wiki update. That work around sadly doesn't work for me, either inheritance or interface. Guess I'll have to wait until EF Core 1.2
Hello @wonea ,
I did a test with your scenario + ForceCast, and it seems to work well.
Here is the full code used, let me know if that helped
Code:
using System.Data.SqlClient;
using System.Linq;
using System.Windows.Forms;
using Microsoft.EntityFrameworkCore;
using Z.Test.EntityFramework.Plus;
namespace Z.EntityFramework.Plus.Lab.EFCore
{
public partial class Form_Request_QueryFilter_WithInheritance : Form
{
public Form_Request_QueryFilter_WithInheritance()
{
InitializeComponent();
// CLEAR
using (var ctx = new CurrentContext())
{
ctx.TestProcesss.RemoveRange(ctx.TestProcesss);
ctx.SaveChanges();
}
// SEED
using (var ctx = new CurrentContext())
{
ctx.TestProcesss.Add(new TestProcess() {Title = ""});
ctx.TestProcesss.Add(new TestProcess() {Title = "A"});
ctx.TestProcesss.Add(new TestProcess() {Title = "B"});
ctx.TestProcesss.Add(new TestProcess() {Title = ""});
ctx.TestProcesss.Add(new TestProcess() {Title = "C"});
ctx.SaveChanges();
}
// TEST
QueryFilterManager.ForceCast = true;
using (var ctx = new CurrentContext())
{
ctx.Filter<IProcess>(q => q.Where(x => x.Title == ""));
var testProcess = ctx.TestProcesss.ToList();
}
}
public class CurrentContext : DbContext
{
public CurrentContext()
{
Database.EnsureCreated();
}
public DbSet<TestProcess> TestProcesss { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(new SqlConnection(My.Config.ConnectionStrings.TestDatabase));
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//foreach (var entity in modelBuilder.Model.GetEntityTypes())
//{
// entity.Relational().TableName = GetType().DeclaringType.FullName.Replace(".", "_") + "_" + entity.DisplayName();
//}
base.OnModelCreating(modelBuilder);
}
}
public interface InheritedTestClass
{
}
public interface IProcess
{
string Title { get; set; }
}
public interface IStuff
{
}
public class TestProcess : InheritedTestClass, IProcess, IStuff
{
public int ID { get; set; }
public string Title { get; set; }
}
}
}
Best Regards,
Jonathan
Forgot to mention, I'm using PostgreSQL
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="1.1.0" />
A little different
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseNpgsql(ConnectionString);
}
}
Hello @wonea ,
Did you try it with my example? I just did the test with PostgreSQL and everything is still working.
using System.ComponentModel.DataAnnotations.Schema;
using System.Configuration;
using System.Linq;
using System.Windows.Forms;
using Microsoft.EntityFrameworkCore;
using Npgsql;
namespace Z.EntityFramework.Plus.Lab.EFCore.PostgreSQL
{
public partial class Form_Request_QueryFilter_WithInheritance : Form
{
public Form_Request_QueryFilter_WithInheritance()
{
InitializeComponent();
// CLEAR
using (var ctx = new CurrentContext())
{
ctx.TestProcesss.RemoveRange(ctx.TestProcesss);
ctx.SaveChanges();
}
// SEED
using (var ctx = new CurrentContext())
{
ctx.TestProcesss.Add(new TestProcess {Title = ""});
ctx.TestProcesss.Add(new TestProcess {Title = "A"});
ctx.TestProcesss.Add(new TestProcess {Title = "B"});
ctx.TestProcesss.Add(new TestProcess {Title = ""});
ctx.TestProcesss.Add(new TestProcess {Title = "C"});
ctx.SaveChanges();
}
// TEST
QueryFilterManager.ForceCast = true;
using (var ctx = new CurrentContext())
{
ctx.Filter<IProcess>(q => q.Where(x => x.Title == ""));
var testProcess = ctx.TestProcesss.ToList();
}
}
public class CurrentContext : DbContext
{
public CurrentContext()
{
Database.EnsureCreated();
}
public DbSet<TestProcess> TestProcesss { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(new NpgsqlConnection(ConfigurationManager.ConnectionStrings["CodeFirstEntities"].ConnectionString));
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//foreach (var entity in modelBuilder.Model.GetEntityTypes())
//{
// entity.Relational().TableName = GetType().DeclaringType.FullName.Replace(".", "_") + "_" + entity.DisplayName();
//}
base.OnModelCreating(modelBuilder);
}
}
public interface InheritedTestClass
{
}
public interface IProcess
{
string Title { get; set; }
}
public interface IStuff
{
}
[Table("TestProcesss", Schema = "dbo")]
public class TestProcess : InheritedTestClass, IProcess, IStuff
{
public int ID { get; set; }
public string Title { get; set; }
}
}
}
Package
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.EntityFrameworkCore" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.EntityFrameworkCore.Relational" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Extensions.Caching.Abstractions" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Extensions.Caching.Memory" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Extensions.DependencyInjection" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.Extensions.Logging" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Extensions.Options" version="1.1.1" targetFramework="net461" />
<package id="Microsoft.Extensions.Primitives" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net461" />
<package id="NETStandard.Library" version="1.6.1" targetFramework="net461" />
<package id="Npgsql" version="3.1.9" targetFramework="net461" />
<package id="Npgsql.EntityFrameworkCore.PostgreSQL" version="1.1.0" targetFramework="net461" />
<package id="Remotion.Linq" version="2.1.1" targetFramework="net461" />
<package id="System.AppContext" version="4.3.0" targetFramework="net461" />
<package id="System.Collections" version="4.3.0" targetFramework="net461" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net461" />
<package id="System.Collections.Immutable" version="1.3.0" targetFramework="net461" />
<package id="System.ComponentModel" version="4.3.0" targetFramework="net461" />
<package id="System.Console" version="4.3.0" targetFramework="net461" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net461" />
<package id="System.Diagnostics.DiagnosticSource" version="4.3.0" targetFramework="net461" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net461" />
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net461" />
<package id="System.Globalization" version="4.3.0" targetFramework="net461" />
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net461" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net461" />
<package id="System.IO" version="4.3.0" targetFramework="net461" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net461" />
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net461" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Linq" version="4.3.0" targetFramework="net461" />
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net461" />
<package id="System.Linq.Queryable" version="4.0.1" targetFramework="net461" />
<package id="System.Net.Http" version="4.3.0" targetFramework="net461" />
<package id="System.Net.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net461" />
<package id="System.ObjectModel" version="4.3.0" targetFramework="net461" />
<package id="System.Reflection" version="4.3.0" targetFramework="net461" />
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net461" />
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net461" />
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net461" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net461" />
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net461" />
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net461" />
<package id="System.Threading" version="4.3.0" targetFramework="net461" />
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net461" />
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net461" />
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net461" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net461" />
</packages>
First of all, this library is great for abstracting the global filtering from individual queries! I am planning to use it for handling global soft delete data filtering in the EF queries.
I am facing few issues while using it in the .net core version. You example above work, but even with the ForceCast = true, the following two scenarios do not work:
Error Message is: No coercion operator is defined between types '<>f__AnonymousType0`1[System.String]' and 'SampleApp.Program+Test+TestProcess'.
The two entities used for joining are:
[Table("Persons", Schema = "dbo")]
public class Persons : InheritedTestClass, IProcess, IStuff
{
public int ID { get; set; }
public string Title { get; set; }
}
[Table("TestProcess", Schema = "dbo")]
public class TestProcess : InheritedTestClass, IProcess, IStuff
{
public int ID { get; set; }
public string Title { get; set; }
}
Can you please help me with these scenarios?
I have the following entity which inherits from an abstract base class (which in turn has an interface and inherited base), and implements an interface.
However the following fail;
and
ctx.Filter<InheritedTestClass>(q => q.Where(x => x.Title == ""));
With this error;
The following works (just to test);
ctx.Filter<TestProcess>(q => q.Where(x => x.Title == ""));
I'm using these references;