簡體   English   中英

從數據庫獲取結果時阻止循環引用

[英]Prevent circular references when getting result from database

如果我有以下簡單模型:

    public class Company
    {
        public Guid CompanyId { get; set; }

        public ICollection<CompanyUser> Users { get; set; }
    }

    public class CompanyUser
    {
        public Guid CompanyId { get; set; }

        public Guid UserId { get; set; }

        public Company Company { get; set; }

        public User User { get; set; }
    }

    public class User
    {
        public Guid UserId { get; set; }

        public ICollection<CompanyUser> Companies { get; set; }
    }

要獲取公司及其用戶+用戶對象的列表,請運行以下查詢:

return await _dataContext.Companies
    .Include(m => m.Users)
    .ThenInclude(m => m.User)
    .OrderBy(m => m.Name)
    .ToListAsync();

結果可行,但我使用映射器通過模型重新定位將結果映射到視圖模型。

會發生的是, Company對象有一個CompanyUser列表的引用,在每個CompanyUser對象中,我們有一個Company ,它再次有一個CompanyUser列表,只是在我們得到堆棧溢出之前不斷重復。

在此輸入圖像描述

映射器非常簡單:

var results = companies.ToViewModel<Company, CompanyViewModel>();
public static IList<TModel> ToViewModel<TEntity, TModel>(this IEnumerable<TEntity> entities)
    where TEntity : class
    where TModel : class, IViewModel<TEntity>, new()
{
    return entities?.Select(entity => entity.ToViewModel<TEntity, TModel>()).ToList();
}

public static TModel ToViewModel<TEntity, TModel>(this TEntity entity)
    where TEntity : class
    where TModel : class, IViewModel<TEntity>, new()
{
    if (entity == null)
    {
        return null;
    }

    var model = new TModel();
    model.ToViewModel(entity);
    return model;
}
public interface IViewModel<in TEntity>
    where TEntity : class
{
    void ToViewModel(TEntity entity);
}

public class CompanyViewModel : IViewModel<Company>
{
    public Guid CompanyId { get; set; }

    public IList<CompanyUserViewModel> Users { get; set; }

    public void ToViewModel(Company entity)
    {
        CompanyId = entity.CompanyId;
        Users = entity.Users.ToViewModel<CompanyUser, CompanyUserViewModel>();
    }
}

public class CompanyUserViewModel : IViewModel<CompanyUser>
{
    public Guid CompanyId { get; set; }

    public Guid UserId { get; set; }

    public CompanyViewModel Company { get; set; }

    public UserViewModel User { get; set; }

    public void ToViewModel(CompanyUser entity)
    {
        CompanyId = entity.CompanyId;
        UserId = entity.UserId;
        Company = entity.Company.ToViewModel<Company, CompanyViewModel>();
        User = entity.User.ToViewModel<User, UserViewModel>();
    }
}

public class UserViewModel : IViewModel<User>
{
    public Guid UserId { get; set; }

    public void ToViewModel(User entity)
    {
        UserId = entity.Id;
    }
}

有沒有辦法阻止這些引用被解決?

您是否願意更改數據模型? 我認為最好的解決方案是刪除循環引用。

如果公司包含用戶列表,用戶是否還需要包含他的CompanyIdCompany對象? 我會刪除public Company Company { get; set; } public Company Company { get; set; } public Company Company { get; set; }從您的CompanyUser對象, Companies從您的User對象。

有多種解決方案:

1)您可以使用automapper而不是自己的映射器。 它具有MaxDepth屬性,可以防止出現此問題:

Mapper.CreateMap<Source, Destination>().MaxDepth(1);

2)您可以從實體中刪除依賴項,並在一個方向上使用陰影屬性。

你的問題是,你映射到CompanyViewModel然后映射到CompanyUserViewModel但這然后再回到映射到CompanyViewModel它創建一個無限循環。

如果你希望總是從Company (以CompanyView ),然后卸下遞歸從后CompanyUserViewModel

public void ToViewModel(CompanyUser entity)
{
    CompanyId = entity.CompanyId;
    UserId = entity.UserId;
    // Company = entity.Company.ToViewModel<Company, CompanyViewModel>();
    User = entity.User.ToViewModel<User, UserViewModel>();
}

或者,不要在ToViewModel映射中映射關系,在基於Ids之后連接關系。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM