将 IQueryable<DomainModel> 转换为 IQueryable<EntityModel> for EntityFramework。



我正试图将IQueryable转换为IQueryable,以允许我利用Linq在EntityFramework上下文中提供的动态过滤。我试图坚持存储库模式,而不是在存储库之外暴露任何与EntityFramework相关的内容。

代码…

My Domain Model

public class Invoice
{
public Invoice()
{
InvoiceItems = new HashSet<InvoiceItem>();
}
public Guid Id { get; set; }
public string Number { get; set; }
public DateTime UtcDate { get; set; }
public DateTime? UtcDueDate { get; set; }
public decimal Amount { get; set; }
public bool IsPublished { get; set; }
public bool IsPosted { get; set; }
public DateTime UtcCreatedAt { get; set; }
public DateTime? UtcUpdatedAt { get; set; }
public DateTime? UtcDeletedAt { get; set; }
public ICollection<InvoiceItem> InvoiceItems { get; set; }
}

我的实体模型

public class InvoiceModel
{
public InvoiceModel()
{
InvoiceItems = new HashSet<InvoiceItemModel>();
}
public int Id { get; set; }
public Guid PublicId { get; set; }
public string Number { get; set; }
public DateTime UtcDate { get; set; }
public DateTime? UtcDueDate { get; set; }
public decimal Amount { get; set; }
public bool IsPublished { get; set; }
public bool IsPosted { get; set; }
public DateTime UtcCreatedAt { get; set; }
public DateTime? UtcUpdatedAt { get; set; }
public DateTime? UtcDeletedAt { get; set; }
public ICollection<InvoiceItemModel> InvoiceItems { get; set; }
}

我的存储库

public class SampleRepository : ISampleRepository
{
private readonly IDbContextFactory<FinancialsSqlDbContext> _factory;
public SampleRepository(IDbContextFactory<FinancialsSqlDbContext> factory)
{
_factory = factory;
}
#region Entity Mapping Methods
private Invoice FromEntity(InvoiceModel invoice)
=> new Invoice
{
Id = invoice.PublicId,
Number = invoice.Number,
UtcDate = invoice.UtcDate,
UtcDueDate = invoice.UtcDueDate,
Amount = invoice.Amount,
IsPublished = invoice.IsPublished,
IsPosted = invoice.IsPosted,
UtcCreatedAt = invoice.UtcCreatedAt,
UtcUpdatedAt = invoice.UtcUpdatedAt,
UtcDeletedAt = invoice.UtcDeletedAt
};
private InvoiceModel ToAddEntity(Invoice invoice)
=> new InvoiceModel
{
Number = invoice.Number,
UtcDate = invoice.UtcDate,
UtcDueDate = invoice.UtcDueDate,
Amount = invoice.Amount,
IsPublished = invoice.IsPublished,
IsPosted = invoice.IsPosted,
UtcCreatedAt = DateTime.UtcNow
};
private InvoiceModel ToUpdateEntity(InvoiceModel model, Invoice invoice)
=> new InvoiceModel
{
Id = model.Id,
PublicId = model.PublicId,
Number = invoice.Number,
UtcDate = invoice.UtcDate,
UtcDueDate = invoice.UtcDueDate,
Amount = invoice.Amount,
IsPublished = invoice.IsPublished,
IsPosted = invoice.IsPosted,
UtcCreatedAt = model.UtcCreatedAt,
UtcUpdatedAt = DateTime.UtcNow
};
private InvoiceModel ToRemoveEntity(InvoiceModel model, Invoice invoice)
=> new InvoiceModel
{
Id = model.Id,
PublicId = model.PublicId,
Number = invoice.Number,
UtcDate = invoice.UtcDate,
UtcDueDate = invoice.UtcDueDate,
Amount = invoice.Amount,
IsPublished = invoice.IsPublished,
IsPosted = invoice.IsPosted,
UtcCreatedAt = model.UtcCreatedAt,
UtcUpdatedAt = model.UtcUpdatedAt
};
#endregion
public async Task<List<Invoice>> ListAsync(Func<IQueryable<Invoice>, IQueryable<Invoice>> predicate = null)
{
using (var context = _factory.CreateDbContext())
{
var query = predicate != null ? predicate.Invoke(new List<Invoice>().AsQueryable()).ToDTO<Invoice, InvoiceModel>() : context.Invoices.AsQueryable();
var result = await query.ToListAsync();
return result.Select(FromEntity).ToList();
}
}
}

抛出的方法是

public async Task<List<Invoice>> ListAsync(Func<IQueryable<Invoice>, IQueryable<Invoice>> predicate = null)
{
using (var context = _factory.CreateDbContext())
{
var query = predicate != null ? predicate.Invoke(new List<Invoice>().AsQueryable()).ToDTO<Invoice, InvoiceModel>() : context.Invoices.AsQueryable();
var result = await query.ToListAsync();
return result.Select(FromEntity).ToList();
}
}

我最近的尝试是从这个答案Cast IQueryableIQueryable当我调用ToListAsync()时不起作用,因为它会抛出以下异常:

System.InvalidOperationException: The source 'IQueryable' doesn't implement 'IAsyncEnumerable<Financials.Server.Data.Sql.Models.InvoiceModel>'. Only sources that implement 'IAsyncEnumerable' can be used for Entity Framework asynchronous operations.
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsAsyncEnumerable[TSource](IQueryable`1 source)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Financials.Server.Data.Sql.Repositories.SampleRepository.ListAsync(Func`2 predicate)

我不太确定做这件事的最好方法,甚至不知道这是否可能。

试试AutoMapper。它允许你从一个实体映射到另一个实体,并且有多种方法来使用IQueryable和EF。如果您有任何问题,请查看此PoC。

最新更新