我的域对象有一个不断更新的对象列表。我现在把这个收藏作为一个清单。但对于每次更新,我都必须不断执行 .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 兼容?
您可以创建一个实现
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)
添加项目,并且仍然获取字典所需的键。