我没有问,如果我要使用Repository模式,我关心的如何。将与持久性相关的对象注入域类对我来说不是一个选择:它使单元测试变得不可能(不,使用内存数据库的测试不是单元测试,因为它们没有隔离地覆盖了许多不同的类),它耦合了域逻辑使用 ORM,它打破了我实践的许多重要原则,例如持久性无知、关注点分离等,欢迎您在线搜索它们的好处。对我来说,“正确”使用 EF Core 并不像保持业务逻辑与外部问题的隔离那么重要,这就是为什么我会接受 EF Core 的“hacky”使用,如果这意味着存储库不会泄漏不再抽象。
让我们假设存储库的界面如下:
public interface IRepository<TEntity>
where TEntity : Entity
{
void Add(TEntity entity);
void Remove(TEntity entity);
Task<TEntity?> FindByIdAsync(Guid id);
}
public abstract class Entity
{
public Entity(Guid id)
{
Id = id;
}
public Guid Id { get; }
}
Run Code Online (Sandbox Code Playgroud)
我在网上看到的大多数 EF Core 实现都做了类似的事情:
public class EFCoreRepository<TEntity> : IRepository<TEntity>
where TEntity : Entity
{
private readonly DbSet<TEntity> entities;
public EFCoreRepository(DbContext dbContext)
{
entities = dbContext.Set<TEntity>();
}
public …Run Code Online (Sandbox Code Playgroud) c# domain-driven-design ddd-repositories repository-pattern entity-framework-core
我有2个或更多属性唯一的模型。例如,该类的对象在Entity名称和ID上都是唯一的。
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我有一个模型存储库:
public class EntityRepository
{
...
public Entity GetById(int id)
{
return db.GetById(id);
}
public Entity GetByName(string name)
{
return db.GetByName(name);
}
}
Run Code Online (Sandbox Code Playgroud)
什么是缓存到两个呼叫的最佳方式GetById,并呼吁GetByName使用Microsoft.Extensions.Caching.Memory.IMemoryCache?
当前解决方案:
public class EntityRepository
{
...
public Entity GetById(int id)
{
return Cache.GetOrCreate($"id:{id}", cacheEntry =>
{
return db.GetById(id);
});
}
public Entity GetByName(string name)
{
return Cache.GetOrCreate($"name:{name}", cacheEntry …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习 DDD 和 Clean Architecture 的一些想法,但遇到了一个问题:如何对应用程序层中的命令处理程序进行单元测试,验证它们在域对象上调用正确的方法,而不测试内部的逻辑那些域对象?假设我有以下域实体:
public class User
{
public User(int id)
{
Id = id;
}
public int Id { get; }
public void RemoveProfilePicture()
{
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
我有以下简单的命令类:
public class RemoveUserProfilePictureCommand : ICommand
{
public RemoveUserProfilePictureCommand(int userId)
{
UserId = userId;
}
public int UserId { get; }
}
Run Code Online (Sandbox Code Playgroud)
和命令处理程序(位于应用程序层):
public class Handler : ICommandHandler<RemoveUserProfilePictureCommand>
{
private readonly IUserRepository userRepository;
public Handler(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
public void Handle(RemoveUserProfilePictureCommand command)
{
var user …Run Code Online (Sandbox Code Playgroud) 当我用同一个接口向DI容器注册多个服务然后请求一个时IEnumerable<IService>,容器是否保证注册的顺序就是集合的顺序?因为这似乎是行为,但我在文档中找不到任何关于它的信息。
示例 - 假设我们有这个接口:
public interface IStep
{
void Execute();
}
Run Code Online (Sandbox Code Playgroud)
以及一些实现:
public class FirstStep : IStep { ... }
public class SecondStep : IStep { ... }
public class ThirdStep : IStep { ... }
...
Run Code Online (Sandbox Code Playgroud)
我们将它们注册到容器中:
services.AddTransient<IStep, FirstStep>();
services.AddTransient<IStep, SecondStep>();
services.AddTransient<IStep, ThirdStep>();
Run Code Online (Sandbox Code Playgroud)
最后请求一个集合IStep:
public class Plan
{
private readonly IEnumerable<IStep> steps;
public Plan(IEnumerable<IStep> steps)
{
this.steps = steps;
}
public void Execute()
{
foreach (var step in steps)
{
step.Execute();
}
}
}
Run Code Online (Sandbox Code Playgroud)
假设步骤将根据注册顺序执行是否可以?如果不是,那么实现类似管道行为的最佳方法是什么?