Как я могу проверить, загружается ли мой объект Entity? - PullRequest
2 голосов
/ 05 февраля 2020

У меня есть два класса сущностей, которые имеют отношение один ко многим.

public class Call : IEntity
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class User : IEntity
{
    public int Id { get; set; }

    public string Username { get; set; }
    public virtual ICollection<Call> Calls { get; set; }
}

И у меня есть модель представления для операций 'Call' на веб-слое.

public class CallVm : IViewModel
{
    public string Id { get; set; }
    public string UserFullname { get; set; }
}

И я использую метод для преобразования моего объекта 'Call' в 'CallVm' объект. Этот метод вкратце выглядит следующим образом.

public CallVm MapCallVm(Call call)
{
    return call == null ? null : new CallVm { Id = call.Id, UserFullname = call.User?.Fullname };
}

Когда я читаю сущность «Вызов» из базы данных, я иногда включаю «Пользователь», а иногда нет. Когда я не включаю его, в объекте Call отсутствует определение свойства User, потому что это ленивая загрузка. Поэтому я получаю следующую ошибку в методе MapCallVm.

Экземпляр ObjectContext был удален и больше не может использоваться для операций, требующих подключения.

Есть ли способ проверить это? Я просто хочу назначить UserFullname = call.User?.Fullname, когда есть напряженная нагрузка. Единственное решение, которое я могу придумать, - это управление с помощью try-catch. Есть ли другое решение?

Ответы [ 2 ]

2 голосов
/ 05 февраля 2020

Можно использовать DbReferenceEntry.IsLoaded Свойство.

Получает или задает значение, указывающее, был ли объект загружен из базы данных.

if (_dbContext.Entry(Call).Reference(e => e.User).IsLoaded)

Обновлено

Если вы получаете значение без dbContext, вместо этого вы должны заставить запрос Eager loading.

Прочтите следующий пост, чтобы получить лучшее понимание.

Следует ли отключить отложенную загрузку Entity Framework в веб-приложениях?

0 голосов
/ 05 февраля 2020

Как @ ответ Фонга - избегать передачи DbContext. Обычно ваш класс репозитория должен отображать сущности БД в простые объекты POCO / DTO.

Я предлагаю ввести класс mapper. Это поможет вам провести модульное тестирование вашей логики c

// Interface to inject to repository
public interface ICallMapper
{
    CallVm Map(Call call);
}

public class CallMapper : ICallMapper
{
    public CallVm Map(Call call)
    {
        return call == null ? null : new CallVm { Id = call.Id, UserFullname = call.User?.Username };
    }
}

Передать маппер в хранилище и убедиться, что ваши объекты больше не связаны с БД

public class CallRepository : ICallRepository
{
    private readonly ICallMapper _callMapper;

    public CallRepository(ICallMapper callMapper)
    {
        _callMapper = callMapper;
    }

    public IList<CallVm> GetList()
    {
        // Call DB and get entities
        var calls = GetCalls();

        // Map DB entities to plain model
        return calls.Select(_callMapper.Map).ToList();
    }
}

Это позволит вам получить избавиться от вашей ошибки. И делает вашу программу более структурированной и тестируемой.

...