在域对象中使用字典的替代方法

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

我的域对象有一个不断更新的对象列表。我现在把这个收藏作为一个清单。但对于每次更新,我都必须不断执行 .Where().FirstOrDefault()。出于我的目的,使用字典会更好,这将使访问我想要的对象更快,但我无法使用字典,因为根本不支持在我的实体配置中映射字典。

using System.Collections.Immutable;

namespace SessionTracker.Domain
{
 public class Session
 {
    private readonly Dictionary<int, SessionScore> _sessionScores = new();
    private readonly List<SessionScore> _lsessionScores = new();

    protected Session() { }

    public Session(int playerId, Dictionary<int, long> startScores, DateTime timestamp)
    {
        PlayerId = playerId;
        StartDateTime = timestamp;
        foreach (var item in startScores)
        {
            if (!_sessionScores.ContainsKey(item.Key))
            {
                _sessionScores.Add(item.Key, new SessionScore(item.Key, item.Value, timestamp));
            }
        }
    }

    public void Update(Dictionary<int, long> startScores, DateTime timestamp)
    {
        foreach (var item in startScores)
        {
            if (!_sessionScores.ContainsKey(item.Key))
            {
                _sessionScores.Add(item.Key, new SessionScore(item.Key, item.Value, timestamp));
            }
            else
            {
                _sessionScores[item.Key].Update(item.Value, timestamp);
            }
        }
    }

    public void End(Dictionary<int, long> startScores, DateTime timestamp)
    {
        foreach (var item in startScores)
        {
            if (!_sessionScores.ContainsKey(item.Key))
            {
                _sessionScores.Add(item.Key, new SessionScore(item.Key, item.Value, timestamp));
            }
            else
            {
                _sessionScores[item.Key].Update(item.Value, timestamp);
            }
        }
        EndDateTime = timestamp;
    }

    public int PlayerId { get; }
    public DateTime StartDateTime { get; }
    public DateTime? EndDateTime { get; private set; }
    public ImmutableDictionary<int, SessionScore> SessionScores => _sessionScores.ToImmutableDictionary();

    public List<SessionScore> LSessionScores => _lsessionScores.ToList();
}

}

我的基础设施层中的 EF Core 配置类,

public class SessionConfiguration : IEntityTypeConfiguration<Session>
{
    public void Configure(EntityTypeBuilder<Session> builder)
    {
        builder.HasKey(ps => ps.Id);

        builder.Property(ps => ps.PlayerId).IsRequired();

        //This is acceptable since LSessionScores is a list
        builder.HasMany(ps => ps.LSessionScores)
            .WithOne()
            .HasForeignKey(sm => sm.SessionId)
            .IsRequired();

        //This is not acceptable since SessionScores is a dictionary
        builder.HasMany(ps => ps.SessionScores)
            .WithOne()
            .HasForeignKey(sm => sm.SessionId)
            .IsRequired();
    }
}

是否有其他方法来设计我的域以使其与 EF Core 兼容?

c# domain-driven-design
1个回答
0
投票

您可以创建一个实现

ICollection<T>
的复合集合(我认为 EF 会对此感到满意)并集成字典。像这样的东西:

public class KeyedCollection<TKey, TValue>(Func<TValue, TKey> getKey) : ICollection<TValue>
    where TKey : notnull
{
    private readonly Dictionary<TKey, TValue> _dictionary = [];
    private readonly List<TValue> _list = [];

    public int Count => _list.Count;

    public bool IsReadOnly => false;

    public void Add(TValue value)
    {
        _list.Add(value);
        _dictionary.Add(getKey(value), value);
    }

    public void Add(TKey key, TValue value)
    {
        _list.Add(value);
        _dictionary.Add(key, value);
    }

    public bool TryGetValue(TKey key, [NotNullWhen(true)] out TValue? value) 
        => _dictionary.TryGetValue(key, out value!);

    public void Clear()
    {
        _list.Clear();
        _dictionary.Clear();
    }

    public bool Contains(TValue item) => _dictionary.ContainsKey(getKey(item));

    public void CopyTo(TValue[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);

    public IEnumerator<TValue> GetEnumerator() => _list.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
    public bool Remove(TValue item)
    {
        _list.Remove(item);
        return _dictionary.Remove(getKey(item));
    }

}

请注意,我使用了 C# 12.0 功能。 主构造函数接受

Func<TValue, TKey> getKey
委托,以便您可以通过
ICollection<TValue>.Add(TValue value)
添加项目,并且仍然获取字典所需的键。

© www.soinside.com 2019 - 2024. All rights reserved.