我正在创建一个网站,数据将从一个外部应用程序发送,该应用程序具有一个充满数据的数据库,网站只需要其中的一部分。“部分”是指每个表中的一些行,但不是全部。
手头的业务是管理慈善券的业务,他们有客户,他们有账户。慈善机构可能希望登录该网站并查看有关支付给他们的款项的信息,而客户可能希望登录并查看有关其帐户的信息。
但是,想要在线登录的客户数量仅占拥有帐户的客户的一小部分。我们希望避免上传所有客户和慈善机构信息,因为这将是大量数据,必须保持最新,而且大部分不会被使用。
当我们有一张已发行的代金券,但客户的账户中没有足够的钱来支付它时,就会出现问题。在这种情况下,代金券被保留,等待客户存款。慈善机构希望查看持有的代金券列表,但不会显示客户姓名,他们只看到代金券的详细信息,例如日期、金额和编号。
理想情况下,我希望网站数据库是完全相关的,但这会导致数据丢失的问题。例如,如果我们上传持有凭证的详细信息,而客户的详细信息不在网站数据库中(因为他们无法通过网站访问),那么作为外键引用,插入到 HeldVouchers 表将失败客户表将指向不在数据库中的客户。
我可以使所有外部引用都可以为空,但这仍然没有帮助,因为客户 ID 不会为空,它将包含主数据库中客户的 ID。
我可以在上传时检查,如果为不在数据库中的客户上传了持有的凭证,那么我可以将 CustomerID 设置为空。这很好,但如果该客户随后想要访问该网站,并且我们上传了他的详细信息,那么我们将不得不更新 HeldVouchers 表。这将导致大量额外的工作,以及大量的额外上传。
有人知道如何处理这个问题吗?到目前为止,我唯一的想法是使 Web 数据库完全非关系(我真的不喜欢这样做),然后将扩展方法添加到将模拟 EF 生成的实体的实体中,除非它们会直接转到适当的 DbSet 并拉出与“外键”引用匹配的任何实体。
我尝试了这个,并提出了一个有效的通用扩展方法,但至少有两个非常严重的缺点......
public static List<T> NavColl<T>(this EntityInterface entity, Func<T, bool> f)
where T : class, EntityInterface {
return Ctx.Set<T>().ToList().Where(f).ToList();
}
(此方法返回相当于一个集合的导航属性。我有一个类似的查找单个实体的方法)。
如果你有一个 Charity 对象(巧妙地命名为“charity”),并且想要获得持有的代金券,你可以做这样的事情......
charity.NavColl<HeldVoucher>(ca => ca.CharityID == charity.ID)
第一个缺点是,我能看到允许将 Func 传递到扩展方法中并且不让 Linq-To-Entities 抛出杂乱无章的唯一方法是在应用 Func之前枚举 DbSet 。如果那里有很多数据,这可能会显着减慢查询速度。
也许更严重的(因为我不认为性能是一个主要问题)是扩展方法需要一个可以工作的上下文。目前,我将实体放在与 EF 模型不同的项目中,因为这允许我引用解决方案中任何项目的实体,而这些项目不需要引用模型的项目。这有助于保持层分离,并允许测试等。
但是,如果扩展方法需要上下文,则实体项目需要对模型项目的引用,这会导致循环引用(因为模型需要了解实体)。我不能将扩展方法放在模型项目中,因为那样我必须从每个想要使用实体的项目中引用它,这违背了将实体拆分到自己的项目中的整个目的。
有人有什么想法吗?抱歉,这是一个有点长的问题,但我想确保我清楚地解释了这个问题。