我目前拥有数据库中几乎每个表的存储库,并希望通过将它们简化为仅聚合根来进一步使自己与DDD保持一致.
我们假设我有以下表格,User并且Phone.每个用户可能有一部或多部电话.如果没有聚合根的概念,我可能会这样做:
//assuming I have the userId in session for example and I want to update a phone number
List<Phone> phones = PhoneRepository.GetPhoneNumberByUserId(userId);
phones[0].Number = “911”;
PhoneRepository.Update(phones[0]);
Run Code Online (Sandbox Code Playgroud)
聚合根的概念在纸上比在实践中更容易理解.我永远不会有不属于用户的电话号码,所以取消PhoneRepository并将电话相关的方法合并到UserRepository中是否有意义?假设答案是肯定的,我将重写先前的代码示例.
我是否允许在UserRepository上有一个返回电话号码的方法?或者它应该始终返回对用户的引用,然后通过用户遍历关系以获取电话号码:
List<Phone> phones = UserRepository.GetPhoneNumbers(userId);
// Or
User user = UserRepository.GetUserWithPhoneNumbers(userId); //this method will join to Phone
Run Code Online (Sandbox Code Playgroud)
无论我采用哪种方式获取手机,假设我修改了其中一种,我该如何更新它们?我有限的理解是,根目录下的对象应该通过root更新,这将引导我选择下面的#1.尽管这对于Entity Framework非常有效,但这似乎非常缺乏描述性,因为读取代码时我不知道我实际更新了什么,即使实体框架在图形中保留了更改对象的选项卡.
UserRepository.Update(user);
// Or
UserRepository.UpdatePhone(phone);
Run Code Online (Sandbox Code Playgroud)
最后,假设我有几个查阅表中并没有真正依赖于任何东西,如CountryCodes,ColorsCodes,SomethingElseCodes.我可能会用它们来填充下拉或其他任何原因.这些独立的存储库吗?它们可以组合成某种逻辑分组/存储库,例如CodesRepository?或者是针对最佳做法的.
c# asp.net domain-driven-design entity-framework entity-framework-4
我知道一般来说List不是线程安全的,但是如果线程从不在列表上执行任何其他操作(例如遍历它),那么简单地将项添加到列表中是否有什么问题?
例:
List<object> list = new List<object>();
Parallel.ForEach(transactions, tran =>
{
list.Add(new object());
});
Run Code Online (Sandbox Code Playgroud) 这两种查询上下文的方式有什么区别吗?
Firm firm = base.context.Firms
.Where(f => f.SomeId == someId)
.Where(f => f.AnotherId == anotherId)
.FirstOrDefault();
Firm firm = base.context.Firms
.Where(f => f.SomeId == someId && f.AnotherId == anotherId)
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
似乎链接完全可以完成AND条件.我不相信你可以链接OR语句.是否有理由更喜欢一个,或者一个更好/更有效的情况?
假设我有一个父实体"Firm"和一些继承自Firm的子实体.假设孩子被命名为"RedFirm","GreenFirm"和"BlueFirm",如果我只想检索RedFirm和GreenFirm实例,那么查询Firm集合的正确方法是什么?
我知道我可以做context.Firms.OfType(RedFirm),但只返回RedFirm实例.无论如何将类型集合传递给OfType或类似的东西?我想这可以通过工会来完成,但我认为这样效率会降低.
我有一个填充a的主线程List<T>.此外,我创建了一个将在不同线程上执行的对象链,需要访问List.原始列表在生成后永远不会被写入.我的想法是将列表传递IEnumerable<T>给在其他线程上执行的对象,主要是因为不允许那些实现这些对象的人错误地写入列表.换句话说,如果保证不写入原始列表,多个线程使用.Where或foreachIEnumerable是否安全?
如果原始集合永远不会改变,我不确定迭代器本身是否是线程安全的.
通常,我的存储库具有用于调试目的的日志记录语句,允许我查看参数的值.最近,我走上了创建通用存储库的道路,该存储库将谓词Expression作为参数获得了极大的灵活性,但是我无法找到一种将条件记录到远程有用位置的正确方法.
示例方法:
public int GetCount<K>(Expression<Func<K, bool>> predicate) where K : class
{
Logger.LogDebugMessage(String.Format("Parameters [predicate: {0}]", predicate == null ? string.Empty : predicate.Body.ToString()));
...
}
Run Code Online (Sandbox Code Playgroud)
你可以看到我现在正在使用Body.ToString(),但结果不是那么可读:
Parameters [predicate: (fa.SomeId == value(NameSpace.SomeClass+<>c__DisplayClass2).SomeId)]
最终我希望看到的内容类似于以下内容:
Parameters [predicate: (fa.SomeId == 1 && fa.Account.Name == "MyName").SomeId)]
从本质上讲,这个日志的值能够在爆炸时知道输入值.有没有什么方法可以强迫API的用户将谓词作为字符串提供?
我有一段代码Parallel.Foreach在要处理的项目列表上运行.每次迭代都会创建一些对象,每个对象都会实例化并处理它自己的Ninject IKernel实例.当对象完成它的工作时,就会释放IKernel.
也就是说,这个代码在我的Windows 7,I7笔记本电脑上运行得非常好.但是,当我将其推送到运行Windows 2008的VPS时,我得到了这个例外.异常不会发生在同一个迭代中,有时会经历10次迭代并抛出异常,有时则会经历数百次异常.显然似乎是一个线程问题,但除了我的VPS之外,它不会发生.如果重要,那么它将在ASP.NET IIS中托管.
System.AggregateException: One or more errors occurred. --->
System.ArgumentOutOfRangeException: Index was out of range.
Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.Generic.List`1.RemoveAt(Int32 index)
at Ninject.KernelBase.Dispose(Boolean disposing)
Run Code Online (Sandbox Code Playgroud)
以下是代码片段:
//Code that creates and disposes the Ninject kernel
using(ninjectInstance = new NinjectInstance())
{
using (var unitOfWork = ninjectInstance.Kernel.Get<NinjectUnitOfWork>())
{
Init();
continueValidation = Validate(tran, ofr);
}
}
public class NinjectInstance : IDisposable
{
public IKernel Kernel { get; private …Run Code Online (Sandbox Code Playgroud) 我一般都是IOC的新手,而且我正在努力了解我想要做的事情是否有意义.我有一个Web表单应用程序,我想在其中创建一个模块来为我定义一些绑定.绑定将用于将存储库注入我的业务经理类,允许我对业务经理进行单元测试.此外,我想使用容器将Entity Framework上下文注入我的存储库,这样它们每个http请求都共享相同的上下文.所以这就是我想知道的:
我知道我需要使用相同的内核实例来管理我的对象创建及其生命周期.例如,如果我想要一个每个httprequest类型的场景,我需要内核的实例在那段时间内可用.如果我需要单身人士怎么办?然后它必须以某种方式应用范围.那么我究竟在哪里存储IKernel实例?看来我可能想在我的Global.asax中使它成为静态,这是正确的方法并且线程安全是一个问题吗?
由于我使用Bind <>来定义我的绑定,当我不应该从UI引用我的数据访问层时,如何在Web/UI层中进行该定义?我的引用看起来像.Web - > .Business - > DataAccess.好像我想告诉内核"他们管理我的数据访问实例,但是在编译时没有引用它们." 像这样的绑定:
//Any object requesting an instance of AdventureWorksEntities will get an instance per request
Bind<AdventureWorksEntities>().ToSelf().InRequestScope();
我觉得我可能不正确地接近这个,谢谢.
c# dependency-injection ninject ioc-container inversion-of-control
我正在努力实现一个自定义成员资格提供程序,它可以对付我数据库中的现有模式,并且有一些想法/问题.
登录控件将自动调用成员资格提供程序的ValidateUser方法,因此无论我如何实现提供程序,登录控件唯一关心的是此方法返回的bool值.令我困惑的是,登录尝试失败可能有很多原因; 用户被锁定,在一段时间内尝试了太多等等.我无法将其传达给控件,因此它可以显示正确的消息.成员提供者的其他属性,如PasswordStrengthRegularExpression,对登录控制也没有任何影响(开箱即用),我希望它会自动以某种方式转换为正则表达式验证器,但这似乎不是案件.
如果Login控件开箱即用的唯一内容(没有手动处理事件并按上述方式进行初始化)是调用成员资格提供程序上的ValidateUser方法,我看不到为什么验证会返回Login控件失败甚至做某些事情,比如根据某个时间窗口限制验证请求.最后我的问题是为什么我甚至会使用会员提供商与登录控制一起使用?看起来它只是针对Yes/No类型响应而设计的,这是非常严格的.
除非我的假设出错,否则Login控件作为成员资格API之间的界面似乎过于严格,无法使用.也许API更适合其他auth控件,如ChangePassword更好,但对于实际的Login控件,我没有看到重点.
我很感激你的想法.
我有一个Windows服务,其中包含一个文件监视器,当文件到达时会引发事件.当一个事件被引发时,我将使用Ninject来创建业务层对象,在它们内部引用了一个Entity Framework上下文,该上下文也是通过Ninject注入的.在我的Web应用程序中,我总是使用InRequestScope作为上下文,在一个请求中,所有业务层对象都使用相同的Entity Framework上下文.在我当前的Windows服务方案中,将实体框架上下文绑定切换到InThreadScope绑定是否足够?
理论上,当服务中的事件处理程序触发它在某个线程下执行时,如果另一个文件同时到达,它将在不同的线程下执行.因此,两个事件都不会共享实体框架上下文,实质上就像Web上的两个不同的http请求一样.
当你看Ninject wiki时,困扰我的一件事是破坏这些线程范围的对象:
.InThreadScope() - 每个线程将创建一个类型的实例.
.InRequestScope() - 将根据Web请求创建一个类型的实例,并在请求结束时销毁.
基于此,我了解InRequestScope对象将在请求结束时(或之后的某个时刻)被销毁(垃圾收集?).然而,这并没有说明InThreadScope对象是如何被销毁的.回到我的例子,当文件观察者事件处理程序方法完成时,线程消失(回到线程池?)注入的InThreadScope-d对象会发生什么?
编辑: 现在有一点很清楚,当使用InThreadScope()时,它不会在filewatcher的处理程序退出时销毁你的对象.我能够通过删除文件夹中的许多文件来重现这一点,并最终获得了相同的线程ID,这导致了与之前完全相同的Entity Framework上下文,因此对于我的应用程序来说,这绝对是不够的.在这种情况下,5分钟后出现的文件可能正在使用之前分配给同一线程的陈旧上下文.