我正在使用.NET 7,我试图从partenaire
表中获取所有数据,以及所有相关数据(多对多)。
我有这三个类:
namespace Kollofid.Core.Entities
{
public class Partenaire : AuditableBaseEntity
{
public string Name { get; set; }
public string? PhoneNumber { get; set; }
public string? Fax { get; set; }
public string? Email { get; set; }
public Guid? CountryId { get; set; }
public Country? Country { get; set; }
public string? City { get; set; }
public string? PostalCode { get; set; }
public string? Address { get; set; }
public string? TaxRegistration { get; set; }
public string? NumeroRegistreCommerce { get; set; }
public string? Note { get; set; }
public IEnumerable<ActivityPartenaire>? PartenaireActivities { get; set; }
public IEnumerable<PartenaireProductLine>? PartenaireProductLines { get; set; }
public IEnumerable<PartenaireHSCode>? PartenaireHSCodes { get; set; }
public virtual ICollection<PartenaireDetailsBancaire>? PartenaireDetailsBancaires { get; set; }
[NotMapped]
public IEnumerable<Guid>? Activities { get; set; }
[NotMapped]
public IEnumerable<Guid>? ProductLines { get; set; }
[NotMapped]
public string? CountryName { get; set; }
}
}
namespace Kollofid.Core.Entities
{
public class Activity : AuditableBaseEntity
{
public string Name { get; set; }
public string? Description { get; set; }
public bool Visible { get; set; }
public IEnumerable<ActivityPartenaire> PartenaireActivities { get; set; }
public Activity()
{
Visible = true;
}
}
}
namespace Kollofid.Core.Entities
{
public class ActivityPartenaire
{
public Guid PartenaireId { get; set; }
public Partenaire Partenaire { get; set; }
public Guid ActivityId { get; set; }
public Activity Activity { get; set; }
}
}
在基础架构AppDbContext
声明中
protected override void OnModelCreating(ModelBuilder builder)
{
builder.AppendGlobalQueryFilter<ISoftDelete>(s => s.DeletedOn == null);
builder.Entity<ActivityPartenaire>().HasKey(pa => new { pa.ActivityId, pa.PartenaireId });
builder.Entity<PartenaireProductLine>().HasKey(pa => new { pa.PartenaireId, pa.ProductLineId });
base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(GetType().Assembly);
}
在ProductRepository
中:
private IQueryable<Partenaire> GetAllAsQueryable()
{
return _dbContext.Partenaires
.Include(x => x.PartenaireActivities)
.Include(x => x.PartenaireProductLines)
.Include(x => x.Country)
.Select(par => new Partenaire
{
Id = par.Id,
Name = par.Name,
PhoneNumber = par.PhoneNumber,
Fax = par.Fax,
Email = par.Email,
Address = par.Address,
City = par.Address,
PostalCode = par.Address,
TaxRegistration = par.TaxRegistration,
NumeroRegistreCommerce = par.NumeroRegistreCommerce,
Note = par.Note,
CountryId = par.CountryId,
CountryName = par.Country.Name,
PartenaireActivities = par.PartenaireActivities.ToList(),
// ProductLines = par.PartenaireProductLines.Select(prod => prod.ProductLineId)
});
}
当我调用GetAllAsQueryable.ToList()
时,我有一个无限循环,我现在得到了异常,屏幕上没有消息。
当我注解掉PartenaireActivities
和ProductLines
时,我得到了数据
我试着只用Guid
填充Activities
,但我遇到了同样的问题。
有人能告诉我是什么问题吗?
我还加了这个
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
1条答案
按热度按时间ars1skjm1#
好的,你把实体关系和投影混合在一起了,当涉及到投影时,不要把实体和投影混合在一起。
您还混合了一个用于返回的方法和
IQueryable<TEntity>
。这是我使用的一个常见的存储库模式,但应该是这样的:在返回IQueryable时,不应尝试将数据投影到新的类示例中。EF将继续应用进一步的过滤,这样对它和一个
Select(x = new TEntity)
几乎肯定会扔在工程几扳手。如果一个像这样的方法和使用它的方法在同一个类中,那是非常没有意义的,只需要使用DbContext。如果您的视图只需要数据的一个子集,那么定义一个简单的视图模型来表示该数据。不要重用实体对象来挑选数据。实体类的示例应该表示数据源中的完整实体。如果您需要视图的某些数据,请创建ViewModel。首先,您可以将查询简化为:
在使用投影时,不需要使用
Include
提前加载。(Select
)现在我们来谈谈活动和产品线。要为“活动”显示哪些数据?把这个放到投影里。例如,如果您希望ActivityId和Name可用,并且只希望Activity可见:
然后是类似的产品线。定义一个简单的视图模型来满足视图的需要,并将其投影下来。
尝试将实体引用传递给视图引擎时,您会遇到各种问题。当您将Partenaire实体向下投影到类的副本中时,您尝试填充Activities和ProductLines的代码只是设置对DbContext中真实的实体的引用,这将包括对真实Partenaire的引用等等。投影到ViewModel可以避免这些问题,并产生更好的查询,副作用更少,但您必须致力于向下投影整个过程,并且不设置实体引用,即使您认为“如果它具有与实体完全相同的字段,那又有什么意义呢?””