EF Core 2.0 menyertakan entitas bersarang dengan kueri dinamis

Saya menggunakan System.Linq.Dynamic.Core; dan metode ekstensi berikut untuk mengakses DbSet secara dinamis berdasarkan nama dan menghasilkan kueri dari string.

Ini adalah metode ekstensi:

namespace Microsoft.EntityFrameworkCore
{
    public static partial class CustomExtensions
    {
        public static IQueryable Query(this DbContext context, string entityName) =>
            context.Query(context.Model.FindEntityType(entityName).ClrType);

        public static IQueryable Query(this DbContext context, Type entityType) =>
            (IQueryable)((IDbSetCache)context).GetOrAddSet(context.GetDependencies().SetSource, entityType);
    }
}

Inilah cara saya mengakses DbSet:

IQueryable<T> dbSet = (IQueryable<T>)_db.Query(entityName);

Ini berfungsi dengan baik, saya dapat membuat kueri dan kemudian membuat daftar tetapi tidak ada entitas bersarang yang dimuat. Tampaknya IQueryable tidak memiliki definisi untuk Include(). Saya dapat melihat metode penyertaan jika saya mengakses konteks db secara langsung dengan cara normal tetapi tidak menggunakan metode dinamis ini.

Bagaimana cara memasukkan entitas bersarang menggunakan metode dinamis?


person Guerrilla    schedule 01.01.2018    source sumber


Jawaban (2)


Pertama-tama Anda menggunakan GetOrAddSet dari IDbSetCache

public interface IDbSetCache

// // Ringkasan: // API ini mendukung infrastruktur Entity Framework Core dan tidak dimaksudkan // untuk digunakan langsung dari kode Anda. API ini mungkin berubah atau dihapus di masa mendatang

Include adalah metode IQueryable<TEntity> di kelas EntityFrameworkQueryableExtensions dari Microsoft.EntityFrameworkCore, bukan untuk IQueryable. Fungsi Anda mengembalikan IQueryable

Saya akan merekomendasikan Anda untuk membuat metode ekstensi seperti di bawah ini,

        public static IQueryable<T> MyQuery<T>(this DbContext context)
            where T : class
        {
            return context.Set<T>().AsQueryable();
        }

Dan Anda dapat mengkonsumsinya dengan,

  var result = _dbContext.MyQuery<Employee>().Include("Department");

Untuk Dinamis termasuk,

    /// <summary>
    /// Query with dynamic Include
    /// </summary>
    /// <typeparam name="T">Entity</typeparam>
    /// <param name="context">dbContext</param>
    /// <param name="includeProperties">includeProperties with ; delimiters</param>
    /// <returns>Constructed query with include properties</returns>
    public static IQueryable<T> MyQueryWithDynamicInclude<T>(this DbContext context, string includeProperties)
       where T : class
    {            
        string[] includes = includeProperties.Split(';');
        var query = context.Set<T>().AsQueryable();

        foreach (string include in includes)
            query = query.Include(include);

        return query;
    }
person programtreasures    schedule 01.01.2018
comment
Ini sangat membantu, terima kasih! Satu kemungkinan perubahan; daripada menyertakan beberapa nama properti dalam string yang sama dan memisahkannya dalam metode, Anda bisa menggunakan params string[] includeProperties sebagai parameter terakhir dalam metode Anda. - person Klicker; 21.04.2020
comment
Bagaimana jika saya juga perlu memasukkan sub-entitas? Parameter inputnya adalah params string[] includeProperties jadi saya akan meneruskan new[] { nameof(SomeClass.MyProperty), nameof(...) ... } tetapi jika Properti Saya adalah Daftar dan saya ingin memasukkan sub propertinya, ada masalah... - person kkamil4sz; 01.09.2020

Saya punya kode bagian untuk masalah ini. Saya menggunakan pohon Ekspresi.

Model entitas saya seperti di bawah ini:

public class PortfolioTechnology
{
    public int PortfolioId { get; set; }
    public Portfolio Portfolio { get; set; }

    public int TechnologyId { get; set; }
    public Technology Technology { get; set; }
}

Kode utama saya seperti di bawah ini:

public SharpListResponse<PortfolioTechnology> GetAll(
    Expression<Func<PortfolioTechnology, bool>> predicate,
    params Expression<Func<PortfolioTechnology,object>>[] includes)
{
    var query = _dbContext.PortfolioTechnology.AsQueryable();

    foreach (var include in includes)
    {
        var memberExpression = include.Body as MemberExpression;

        if (memberExpression != null)
            query = query.Include(memberExpression.Member.Name);
    }

    var result = query.Where(predicate).ToList();

    return new SharpListResponse<PortfolioTechnology>(result);
}

Dan gunakan metode ini seperti di bawah ini:

var list = _unitOfWork.PortfolioTechnologyRepository.GetAll(x => x.PortfolioId == id, 
                                                            y => y.Technology);

Jika Anda ingin memasukkan beberapa entitas misalnya mencakup entitas Portofolio dan Teknologi, kode Anda seperti di bawah ini:

 var list = _unitOfWork.PortfolioTechnologyRepository.GetAll(x => x.PortfolioId == id, 
                                                             y => y.Technology,
                                                             x => x.Portfolio);

Catatan: SharpListResponse adalah kelas pembungkus. Kode berfungsi tanpanya

Detail lebih lanjut untuk SharpListResponse : https://www.nuget.org/packages/SharpRequestResponseWrapper/

person Ramil Aliyev    schedule 22.03.2020
comment
Solusi luar biasa. Jauh lebih rapi dibandingkan menggunakan string. - person D2TheC; 11.11.2020