public interface IEntity { string Id { get; set; } } public class Customer : IEntity { public string Id { get; set; } public string Name { get; set; } } public class MyDbContext : DbContext { public string FindById<TEntity>(string id) where TEntity: class, IEntity { return DbSet<TEntity>().FirstOrDefault(x => x.Id == "id"); } }
.Lambda #Lambda1<System.Func`2[Sam.DbContext.Customer,System.Boolean]>(Sam.DbContext.Customer $x) { $x.Id == "id" }
.Lambda #Lambda1<System.Func`2[Sam.DbContext.Customer,System.Boolean]>(Sam.DbContext.Customer $x) { ((Sam.DbContext.IEntity)$x).Id == "id" }
Unable to cast the type 'Sam.DbContext.Customer' to type 'Sam.DbContext.IEntity'. LINQ to Entities only supports casting EDM primitive or enumeration types.
using System; using System.Linq.Expressions; using System.Reflection; namespace Sam.Extensions.Expressions { /// <summary> /// Removes unnessesary Convert() operands (inserted by Roslyn, but not supported by EF). /// </summary> public class SimplifyExpression : ExpressionVisitor { /// <summary> /// Simplificates the <paramref name="sourceExpression"/>. /// </summary> /// <param name="sourceExpression">Source expression</param> public static Expression Execute(Expression sourceExpression) { return new SimplifyExpression().Visit(sourceExpression); } /// <summary> /// Creates and simplificates the <paramref name="predicateExpression"/>. /// Can be used when building EnituyFramework LINQ. /// <example> /// var res = Db.Set{TEntity}().First(SimplifyExpression.Predicate{TEntity}(x => x.Id == id)); /// </example> /// </summary> /// <typeparam name="T">Predicate source type.</typeparam> /// <param name="predicateExpression">Predicate expression</param> public static Expression<Func<T, bool>> Predicate<T>(Expression<Func<T, bool>> predicateExpression) { return predicateExpression.Simplify(); } protected override Expression VisitUnary(UnaryExpression node) { // Replace explicit Convert to implicit one. (Except converion to Object). if (node.Type != typeof(object) && node.Type.IsAssignableFrom(node.Operand.Type)) return Visit(node.Operand); return base.VisitUnary(node); } }
return DbSet<TEntity>().FirstOrDefault(SimplifyExpression.Predicate<TEntity>(x => x.Id == "id"));
public class MyDbContext : DbContext { public string FindById<TEntity>(string id) where TEntity: class, IEntity { return (TEntity)((IQueryable<IEntity>)(DbSet<TEntity>())).FirstOrDefault(x => x.Id == "id"); } }
Source: https://habr.com/ru/post/269139/
All Articles