Skip to content

Instantly share code, notes, and snippets.

@joakimriedel
Last active September 12, 2019 12:03
Show Gist options
  • Save joakimriedel/312a2aaa3c27ec18318881619439e867 to your computer and use it in GitHub Desktop.
Save joakimriedel/312a2aaa3c27ec18318881619439e867 to your computer and use it in GitHub Desktop.
Ef Core 3.0 Expression Bug
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" />-->
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0-rc1.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-rc1.*" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-rc1.*" />
</ItemGroup>
</Project>
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace EfCoreBugExpression
{
class Program
{
static Expression<Func<T, bool>> HasAction<T>(OfferActions action)
where T : IOffer
{
Expression<Func<OfferAction, bool>> predicate = oa => oa.Action == action;
return v => v.Actions.AsQueryable().Any(predicate);
}
static async Task Main(string[] args)
{
using (var context = new ClientContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var expression = HasAction<Offer>(OfferActions.Accepted);
var query = await context.Offers.Where(expression).CountAsync();
// query == 1
}
}
public interface IOffer
{
ICollection<OfferAction> Actions { get; set; }
}
public class Offer : IOffer
{
public int Id { get; set; }
// navigation properties
public ICollection<OfferAction> Actions { get; set; }
}
public enum OfferActions : int
{
Accepted = 1,
Declined = 2
}
public class OfferAction
{
public int Id { get; set; }
[Required]
public Offer Offer { get; set; }
public int OfferId { get; set; }
[Required]
public OfferActions Action { get; set; }
}
class ClientContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// TO USE SQL
optionsBuilder
.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=EfCoreBugExpression;Trusted_Connection=True;MultipleActiveResultSets=true;Connect Timeout=30");
// TO USE INMEMORY
//optionsBuilder
// .UseInMemoryDatabase(Guid.NewGuid().ToString());
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Offer>().HasData(new Offer
{
Id = 1
});
builder.Entity<OfferAction>().HasData(new OfferAction()
{
Id = 1,
OfferId = 1,
Action = Program.OfferActions.Accepted
});
}
public DbSet<Offer> Offers { get; set; }
public DbSet<OfferAction> OfferActions { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment