I have been using the new MVC framework with StructureMap recently and have had good results overall, however, I keep running into a very strange error that I cannot understand or work out how to resolve.
This is my architecture:
I therefore have:
public class Repo : IRepository
{
public Repo(DBContext db)
{
.....
}
}
public …Run Code Online (Sandbox Code Playgroud) 我正在尝试如何为ASP.NET MVC3配置StructureMap我已经使用NuGet,我注意到它创建了一个名为StructuremapMVC的cs文件的App_Start文件夹,所以我检查它并注意到它是相同的代码但是简化了将在Global.asax上的App_Start部分手动编写...
这是我在IoC Class中的代码
public static class IoC
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.AddAllTypesOf<IController>();
});
x.For<OpcionDB>().Use(() => new DatabaseFactory().Get());
});
return ObjectFactory.Container;
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么当我在控制器上注入一些IoC时会出现异常(我使用这种模式:实体框架4 CTP 4/CTP 5通用存储库模式和单元可测试):
private readonly IAsambleaRepository _aRep;
private readonly IUnitOfWork _uOw;
public AsambleaController(IAsambleaRepository aRep, IUnitOfWork uOw)
{
_aRep = aRep;
this._uOw = uOw;
}
public ActionResult List(string period)
{
var rs = _aRep.ByPeriodo(period).ToList<Asamblea>();
return View();
}
Run Code Online (Sandbox Code Playgroud)
例外显示:
Exception Details: System.MissingMethodException: No parameterless constructor defined …Run Code Online (Sandbox Code Playgroud) structuremap asp.net-mvc entity-framework code-first asp.net-mvc-3
计算器:
public interface ICalculator
{
int Calculate(int a, int b);
}
public class Calculator : ICalculator
{
private readonly ICalculatorStrategy _calculatorStrategy;
public Calculator(ICalculatorStrategy calculatorStrategy)
{
_calculatorStrategy = calculatorStrategy;
}
public int Calculate(int a, int b)
{
return _calculatorStrategy.Calculate(a, b);
}
}
Run Code Online (Sandbox Code Playgroud)
计算器stragies:
public interface ICalculatorStrategy
{
int Calculate(int a, int b);
}
public class AdditionCalculator : ICalculatorStrategy
{
public int Calculate(int a, int b)
{
return a + b;
}
}
public class MultiplyCalculator : ICalculatorStrategy
{
public int Calculate(int …Run Code Online (Sandbox Code Playgroud) 我们在Windows Azure和SQL Azure上运行了一组5个在线拍卖系统.每个系统由一个Web工作者和一个或多个Web角色组成.每个系统都使用ASP.NET MVC 3和Entity Framework,Repository Pattern和StructureMap.
工作者角色负责管理并运行两组流程.一组每十秒运行一次,另一组每秒运行一次.每个进程都可能运行数据库查询或存储过程.这些都是使用Quartz.net安排的
Web角色服务于公共接口和后台.在其他基本的crud功能中,这两者都提供了屏幕,当打开时,它们将重复调用控制器方法,这将导致执行存储过程只读查询.每个客户重复的频率约为2-3秒.一个典型的用例是打开5个后台办公室窗口,打开25个最终用户窗口 - 所有窗口都反复点击系统.
很长一段时间以来,我们一直遇到间歇性的SQL超时错误.其中三个最常见的是:
System.Data.SqlClient.SqlException:从服务器接收结果时发生传输级错误.(提供程序:TCP提供程序,错误:0 - 远程主机强制关闭现有连接.)
System.Data.SqlClient.SqlException:从服务器接收结果时发生传输级错误.(提供者:TCP提供者,错误:0 - 信号量超时期限已过期.)
System.Data.SqlClient.SqlException:超时已过期.操作完成之前经过的超时时间或服务器没有响应.
唯一可预测的情况是在拍卖期间,特定控制器 - > sproc在事件期间开始超时(可能是由于负载).所有其他时间错误似乎是完全随机的,即使在用户不活动期间也会出现单个,两个和三个等.例如,系统将在没有错误的情况下运行18个小时,然后可能是来自不同管理方法的5-10个错误,或者可能是用户登录并查看其帐户.
其他信息:
我尝试使用本地SSMS和Azure基于Web的查询工具在SQL Azure上运行受影响的查询/ sprocs - 所有似乎都快速执行,最多1秒.查询计划没有显示任何过于可疑的事情,虽然我绝不是SQL查询性能专家,或任何其他类型的专家J
我们已将所有受影响的区域包装在Azure SQL Transient Fault Handling Blocks中 - 但正如此处所讨论的那样http://social.msdn.microsoft.com/Forums/en-US/ssdsgetstarted/thread/7a50985d-92c2-472f-9464-a6591efec4b3,他们没有抓住超时,根据"Valery M",这是有充分理由的.
虽然asp.net成员资格信息存储在数据库中,但我们不会在数据库中存储任何会话信息.
我们使用1个"SQL Azure服务器实例",它承载所有5个数据库,两个用于登台,三个用于生产.所有5个系统通常同时处于活动状态,尽管在任何给定时间不可能有多个系统处于活动负载状态.所有Web角色,辅助角色和SQL Azure服务器都位于同一Azure地理区域中.
关于我们应该在哪里寻找的任何想法?它是否有助于为每个系统提供自己的SQL Azure服务器?...我们自己的解决方案失败了 - 是否有可能让微软打开一张支持票,并了解我们的应用程序正在进行的工作 - 如何解决这个问题?
提前致谢.
宜兰
我最近买了一本关于 MVVM 的非常好的书 - Silverlight 和 WPF 企业架构的 MVVM 生存指南
不幸的是,与 IoC 相关的部分有很多用于 StructureMap 的代码示例,但不适用于 Silverlight
任何人都可以指向我一个链接,可以帮助我将结构映射代码转换为 Autofac,这是我正在使用的注入工具
代码使用工厂方法创建类和引导程序
using Northwind.ViewModel;
using StructureMap;
namespace Northwind.UI.WPF
{
public class BootStrapper
{
public MainWindowViewModel MainWindowViewModel
{
get
{
return ObjectFactory
.GetInstance<MainWindowViewModel>();
}
}
public BootStrapper()
{
ObjectFactory.Initialize(
o => o.Scan(
a =>
{
a.WithDefaultConventions();
a.AssembliesFromApplicationBaseDirectory(
d => d.FullName
.StartsWith("Northwind"));
a.LookForRegistries();
}));
}
}
using StructureMap;
namespace Northwind.ViewModel
{
public class CustomerDetailsViewModelFactory
: ICustomerDetailsViewModelFactory
{
private readonly IContainer _container;
public CustomerDetailsViewModelFactory(
IContainer container) …Run Code Online (Sandbox Code Playgroud) 我正在使用ServiceStack/StructureMap/Moq.该服务调用Session,类型为ServiceStack.CacheAccess.ISession.对于单元测试,我使用Moq创建了一个Mock对象,并将其添加到StructureMap配置中:
protected Mock<ISession> sessionMock = new Mock<ISession>();
ObjectFactory.Configure(
cfg =>
{
cfg.For<ISession>().Use(sessionMock.Object);
Run Code Online (Sandbox Code Playgroud)
但是,当Session对象为null时,我并不感到惊讶 - 我很确定我会退出一步.使用模拟对象填充Session属性还需要做什么?
[编辑]这是一个简单的测试场景
要测试的代码.简单的请求/服务
[Route("getKey/{key}")]
public class MyRequest:IReturn<string>
{
public string Key { get; set; }
}
public class MyService:Service
{
public string Get(MyRequest request)
{
return (string) Session[request.Key];
}
}
Run Code Online (Sandbox Code Playgroud)
基础测试类和MockSession类
// test base class
public abstract class MyTestBase : TestBase
{
protected IRestClient Client { get; set; }
protected override void Configure(Container container)
{
// this code is never reached under any of my scenarios …Run Code Online (Sandbox Code Playgroud) 我在我们的解决方案中使用NServiceBus v4.3,MVC4,RavenDB 2.5和StructureMap 2.6.4.
我在StructureMap下遇到类似问题的问题,在这个问题的回答中我要求MVC控制器使用不同的生命周期,NServiceBus Handler在我的Web项目中使用RavenDB的IDocumentSession.
特别是在我的情况下,如果我使用HybridHttpOrThreadLocalScoped(如上面的答案建议Windsor)生命周期,会话没有被妥善处理,我很快就达到了30个事务限制错误.如果我使用HttpContext生命周期,则不会调用Web项目中的NSB事件处理程序.
在我的控制器中,会话被包含在通过MVC ActionFilter应用的工作单元中.我也使用处理程序中的UoW,因为我的注册表已连线以从UoW检索会话.代码是这样的:
RavenDbWebRegistry.cs
public sealed class RavenDbWebRegistry : Registry
{
public RavenDbWebRegistry()
{
// register RavenDB document store
ForSingletonOf<IDocumentStore>().Use(() =>
{
var documentStore = new DocumentStore
{
ConnectionStringName = "RavenDB",
Conventions =
{
IdentityPartsSeparator = "-",
JsonContractResolver = new PrivatePropertySetterResolver(),
},
};
documentStore.Initialize();
return documentStore;
});
For<IDocumentSession>().HybridHttpOrThreadLocalScoped().Add(ctx =>
{
var uow = (IRavenDbUnitOfWork)ctx.GetInstance<IUnitOfWork>();
return uow.DocumentSession;
});
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<WebRavenDbUnitOfWork>();
}
}
Run Code Online (Sandbox Code Playgroud)
Web项目处理程序示例:
public class SiteCreatedEventHandler : IHandleMessages<ISiteCreatedEvent>
{
public IBus Bus …Run Code Online (Sandbox Code Playgroud) 我使用Structuremap作为我的依赖关系解析器.我试图在我的Global.asax.cs文件上实现Container Per Request Pattern.
public IContainer Container
{
get
{
return (IContainer)HttpContext.Current.Items["_Container"];
}
set
{
HttpContext.Current.Items["_Container"] = value;
}
}
public void Application_BeginRequest()
{
Container = ObjectFactory.Container.GetNestedContainer();
}
Run Code Online (Sandbox Code Playgroud)
由于在将来的Structuremap版本中不支持ObjectFactory,我希望从DependencyResolver访问容器.怎么可能?
提前致谢.
Noufal
我在使用StructureMap构造函数中存在可为空参数的服务时遇到了一些困难.即
public JustGivingService(IRestClient restClient = null)
Run Code Online (Sandbox Code Playgroud)
在我的配置中,与所有其他服务一起,我通常能够以最小的方式逃脱,所以这里的问题可能只是缺乏理解.我这样做:
container.For<IJustGivingService>().Use<JustGivingService>()
Run Code Online (Sandbox Code Playgroud)
但是,由于可以为空的参数,我会发现我需要使用它来使其工作:
RestClient restClient = null;
container.For<IJustGivingService>().Use<JustGivingService>()
.Ctor<IRestClient>("restClient").Is(restClient);
Run Code Online (Sandbox Code Playgroud)
然而,这对我来说确实有点脏,我觉得这可能是我想要实现的解决方案,而不是标准的方法.如果有更好的方法可以做到这一点,附带的信息将非常感谢.
好的,我收到堆栈错误。它被捕获的文件在这里
using System.Web;
using NHibernate;
using Nichols.Web.App_Start;
namespace Nichols.Web.DependencyResolution
{
public class StructureMapScopeModule : IHttpModule
{
public void Dispose()
{
StructuremapMvc.StructureMapDependencyScope.Dispose();
}
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) =>
{
InitializeNestedContainerForRequest();
var session = GetCurrentSession();
session.BeginTransaction();
};
context.EndRequest += (sender, e) =>
{
var session = GetCurrentSession();
if (context.Context.Error == null
&& IsOk(context.Response.StatusCode))
{
session.Transaction.Commit();
}
else
{
session.Transaction.Rollback();
}
DisposeNestedContainerForRequest();
};
}
private ISession GetCurrentSession()
{
var container = StructuremapMvc.StructureMapDependencyScope.CurrentNestedContainer;
return container.GetInstance<ISession>();
}
private void InitializeNestedContainerForRequest() …Run Code Online (Sandbox Code Playgroud) structuremap ×10
asp.net-mvc ×5
c# ×4
autofac ×1
azure ×1
code-first ×1
linq-to-sql ×1
moq ×1
nservicebus ×1
ravendb ×1
servicestack ×1
silverlight ×1
sql ×1