将实体框架中的一对多引用映射为 ids 集合,而不是实际的实体引用

问题描述 投票:0回答:2

在 Fluent Nhibernate 中,我可以将多个实体引用 1-M 映射为 int id 列表:

    public class User{
     List<int> LicensesIds{
      get;
      set;
    }

而不是

Public class User{
 ICollectoin<License> Licenses{
  get;
  set;
 }
}

这就是实体框架如何映射它的。 在流畅的映射中,当我查询数据库时,我使用 ids 列表而不是实体列表来获取它。

我可以在实体框架中以相同的方式映射它吗?

我需要它的原因是因为我正在使用存储库模式并为域中的每个实体创建了一个存储库:存储库,并且当我使用查询数据库时,我不想定义要查询和获取实体的什么关系LINQ 或在属性调用中间进行延迟绑定,而我不知道该属性调用现在将从数据库中获取数据。 我想通过查询相关存储库来手动引入实体。

谢谢,

詹姆斯

entity-framework fluent-nhibernate one-to-many
2个回答
1
投票

这是不可能的。如果您希望 EF 为您处理加载,您必须始终在实体中拥有许可证列表(您可以公开第二个属性,仅投影到整数列表)。如果您只想在存储库中实现 int 列表,该逻辑将执行额外的查询并填充它。


0
投票

我为实体框架创建了一个解决这个问题的服务:

首先我们进行设置:

public abstract class BaseEntity
{
    public Guid Id { get; set; }
    // Other common properties...
}


public class Book : BaseEntity
{
    public string Title { get; set; }
    // Other properties...
}


public class Person : BaseEntity
{
    public virtual ICollection<Book> Books { get; private set; }
    // Other properties...
}

我们需要存储库:

public interface ICrudRepository<T> where T : BaseEntity
{
    Task<T> GetByIdAsync(Guid id);
    Task<List<T>> GetToListAsync();
    Task CreateAsync(T entity);
    // Additional CRUD operations as needed...
}

public class BookRepository : ICrudRepository<Person>
{
    // The base class already provides the necessary CRUD operations.
    // Additional specific methods for Person can be added here if needed.
}

public class PersonRepository : ICrudRepository<Person>
{
    // The base class already provides the necessary CRUD operations.
    // Additional specific methods for Person can be added here if needed.
}

public class CrudRepository<T> : ICrudRepository<T> where T :  BaseEntity, new()
{
    private readonly List<T> _entities = new List<T>();

public async Task<T> GetByIdAsync(Guid id)
{
    // Simulates asynchronous operation
    return await Task.FromResult(_entities.FirstOrDefault(e => e.Id == id));
}

    public async Task<List<T>> GetToListAsync()
    {
        // Simulate asynchronous operation
        return await Task.FromResult(_entities.ToList());
    }

    public async Task CreateAsync(T entity)
    {
        _entities.Add(entity);
        await Task.CompletedTask;
    }

    // Implement other CRUD methods as necessary...
}

然后我们有一个通用方法,根据 ids 更新集合:

public class CollectionUpdaterService
{
    public async Task ReplaceCollectionItems<TEntity, TSubEntity>(
        ICrudRepository<TSubEntity> repository,
        List<Guid> ids,
        TEntity entity,
        Expression<Func<TEntity, ICollection<TSubEntity>>> collectionPropertySelector)
        where TEntity : BaseEntity
        where TSubEntity : BaseEntity
    {
        if (!ids.Any()) return;

        var subEntities = await repository.GetFilteredToListAsync(x => ids.Contains(x.Id));

        // Compile and invoke the selector
        var collectionProperty = collectionPropertySelector.Compile().Invoke(entity);

        // If the collection is null, initialize it
        if (collectionProperty == null)
        {
            collectionProperty = new List<TSubEntity>();
            var propertyInfo = (collectionPropertySelector.Body as MemberExpression)?.Member as PropertyInfo;
            propertyInfo?.SetValue(entity, collectionProperty);
        }

        collectionProperty.Clear();
        foreach (var subEntity in subEntities)
        {
            collectionProperty.Add(subEntity);
        }
    }
}

用途:

    var bookIds = new List<int>{1,2,3};

    var person = _personRepository.GetById(1);

    await _collectionUpdaterService.ReplaceCollectionItems( _bookRepository, bookIds , person, person => person.Books);
© www.soinside.com 2019 - 2024. All rights reserved.