gpt4 book ai didi

c# - 使用 EF 正确实现存储库

转载 作者:行者123 更新时间:2023-11-30 18:24:08 24 4
gpt4 key购买 nike

我正在尝试使用持久性和领域模型来实现存储库。我的主要目标是将领域逻辑与其他层分开,就像在洋葱架构中一样。

作为我的存储库,我使用 Entity Framework 6.2。为了在模型之间进行映射,我使用了 Automapper。

我不想使用实体模型作为我的领域模型。

我已经阅读了很多有关 DDD 中存储库的概念和想法,浏览了很多示例,但没有一个给我一个如何处理更复杂模型的答案。

例如,在我的 playground 控制台应用程序中,我有 AppUser,其中包含 BankAccounts。当我向用户添加新的 BankAccount 时,我得到了一个额外的行,其中包含未跟踪的 BankAccount 实体。这是因为在从域模型映射到持久性模型(又名实体)时,EF 无法说明跟踪了哪些 BankAccounts 并将它们全部视为新的。

之前

+------------------------------------+
|Id |BankAccountNumber |AppUser_Id |
+------------------------------------+
|1 |Seeded Bank Account | 1 |
+------------------------------------+

之后

+------------------------------------+
|Id |BankAccountNumber |AppUser_Id |
+------------------------------------+
|1 |Seeded Bank Account | NULL |
+------------------------------------+
|2 |Added Bank Account | 1 |
+------------------------------------+
|3 |Seeded Bank Account | 1 |
+------------------------------------+

那是我的代码。

class Program
{
static void Main(string[] args)
{
CreateMappings();

var appUserRepository = new AppUserRepository();

var appUser = appUserRepository.Get(1);

var bankAccount = new BankAccountDM
{
BankAccountNumber = "Added Bank Account"
};

var service = new AppUserDomainSerivce(appUserRepository);
service.AddBankAccount(bankAccount, appUser);

Console.WriteLine("== END ==");
Console.ReadKey();
}

public static void CreateMappings()
{
// Config Automapper
Mapper.CreateMap<AppUserDM, AppUser>()
.ForMember(x => x.Id, opt => opt.MapFrom(y => y.Id))
.ForMember(x => x.Name, opt => opt.MapFrom(y => y.Name))
.ForMember(x => x.BankAccounts, opt => opt.MapFrom((y => y.BankAccounts)))
.ReverseMap();

Mapper.CreateMap<BankAccountDM, BankAccount>()
.ReverseMap();
}

public class AppUserDomainSerivce
{
private readonly AppUserRepository _appUserRepository;

public AppUserDomainSerivce(AppUserRepository appUserRepository)
{
_appUserRepository = appUserRepository;
}

public void AddBankAccount(BankAccountDM bankAccount, AppUserDM appUser)
{
appUser.BankAccounts.Add(bankAccount);

// Save changes
_appUserRepository.Save(appUser);
}
}

public class AppUserRepository
{
public AppUserDM Get(int id)
{
using (var ctx = new AppContext())
{
var userEntity = GetAppUser(id, ctx);
return Mapper.Map<AppUserDM>(userEntity);
}
}

public void Save(AppUserDM user)
{
// Save entity in storage
using (var ctx = new AppContext())
{
var userEntity = GetAppUser(user.Id, ctx);
userEntity = Mapper.Map(user, userEntity);

ctx.SaveChanges();
}
}

private AppUser GetAppUser(int id, AppContext ctx)
{
return ctx.AppUsers
.Include("BankAccounts")
.SingleOrDefault(x => x.Id == id);
}
}
}


// Entities and Domain Models

public class BankAccountDM
{
public int Id { get; set; }
public string BankAccountNumber { get; set; }
}

public class BankAccount
{
[Key]
public int Id { get; set; }
public string BankAccountNumber { get; set; }
}

public class AppUserDM
{
public int Id { get; set; }
public List<BankAccountDM> BankAccounts { get; set; }
public string Name { get; set; }
}

public class AppUser
{
[Key]
public int Id { get; set; }
public virtual ICollection<BankAccount> BankAccounts { get; set; }
public string Name { get; set; }
}


// Entity DbContext

public class AppContext : DbContext
{
public AppContext() : base("AppContext")
{
}

public DbSet<AppUser> AppUsers { get; set; }
}

public Configuration()
{
AutomaticMigrationsEnabled = true;
}

protected override void Seed(ConsoleApplication1.AppContext context)
{
context.AppUsers.Add(new AppUser()
{
// This AppUser will get ID = 1 once saved into DB
Name = "My Test User",
BankAccounts = new List<BankAccount>()
{
new BankAccount()
{
BankAccountNumber = "Seeded Bank Account"
}
}
});
}

最佳答案

如果我使用你的方法(没有事件源);在 reposiyory 的保存方法中,我通常从数据库中读取整个聚合,然后与给定的进行比较。

当然,我们检查从数据库读取的聚合版本是否与我们要保存的聚合相同。因此,存储库中的单一保存方法可以处理域实体和值对象中的添加和删除。

或者您也可以在每个聚合实体值对象中保存一个状态(新建、修改、删除等)。

关于将聚合存储为json; this post from Vaugh Vernon可以是一个有用的开始。

关于c# - 使用 EF 正确实现存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31636597/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com