【问题标题】:How to use RavenDB queries in Data Layer or Classes?如何在数据层或类中使用 RavenDB 查询?
【发布时间】:2014-07-15 21:47:43
【问题描述】:

我已经在我的 MVC 应用程序中嵌入了 RavenDB。我按照所有教程制作RavenController,我可以在控制器中查询Session。

现在我真的很想摆脱在控制器中混合数据并创建一个数据层,这样我就可以做一些业务逻辑来帮助我创建复杂的视图模型。

如何在普通类文件中查询Session?我似乎找不到任何有关如何执行此操作的信息。

【问题讨论】:

    标签: asp.net-mvc ravendb n-tier-architecture


    【解决方案1】:

    依赖注入非常适合这个。您无需创建必要的服务,而是让容器管理组件的生命周期,包括将 IDocumentSession 范围限定为每个 HTTP 请求的一个实例。

    例如,使用Autofac(你需要Autofac 和Autofac.Mvc5 包)你可以在你的App_Start 文件夹中有一个这样的类,然后从你的Global.asax 调用AutofacConfig.Configure() :

    public static class AutofacConfig
    {
        public static IContainer Container { get; private set; }
    
        public static void Configure()
        {
            var builder = new ContainerBuilder();
            var thisAssembly = Assembly.GetExecutingAssembly();
    
            // Register our controllers with the container
            builder.RegisterControllers(thisAssembly).PropertiesAutowired(PropertyWiringOptions.PreserveSetValues);
    
            // Provide injections of the HTTP abstractions (HttpContextBase, etc.)
            builder.RegisterModule(new AutofacWebTypesModule());
    
            // Create and register the Raven IDocumentStore
            builder.Register(c =>
            {
                var store = new DocumentStore {ConnectionStringName = "RavenDB"};
                store.Initialize();
    
                Raven.Client.Indexes.IndexCreation.CreateIndexes(typeof (MvcApplication).Assembly, store);
    
                return store;
            })
                .As<IDocumentStore>()
                .SingleInstance();
    
            // Provide injection of Raven IDocumentSession
            builder.Register(c => c.Resolve<IDocumentStore>().OpenSession())
                .InstancePerRequest();
    
            Container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(Container));
        }
    }
    

    然后,当您在控制器之外的某个地方需要 IDocumentSession 时:

    // Business logic, or other class that injection is not provided for.
    var session = AutofacConfig.Container.Resolve<IDocumentSession>();
    

    还包括 autofac 否则你会得到一个错误说“不包含定义Resolve ...”

    using Autofac;
    

    您可以对大多数其他 DI 容器库做类似的事情; API 只是略有不同。

    【讨论】:

    【解决方案2】:

    HttpContext.Current.Session 持有当前会话,但您绝对不应该在业务逻辑层使用它。业务逻辑层不应该知道HttpContext。

    这个问题的基本解决方案是创建接口:

    public interface ISession 
    {
        int SomeValue { get; set; }
    }
    

    和实施

    public class HttpContextBasedSession : ISession 
    {
        public int SomeValue
        {
            get
            {
                return Convert.ToInt32(HttpContext.Current.Session["SomeValue"]);
            }
    
            set
            {
                HttpContext.Current.Session["SomeValue"] = value;
            }
        }
    }
    

    与依赖注入框架绑定。

    【讨论】:

    • 谢谢。我知道这一点 - 但我认为 Session 在这里是模棱两可的,抱歉,因为 RavenDB 是 DocuemntStore Session。(除非我不正确)这是否意味着我必须创建一个打开 DocuemtStore 并且类似于 LINQ2SQL 的辅助类使用 DBML,然后使用它来查询业务中的数据库?
    • @ppumkin:说来话长。您可能应该对工作单元和存储库模式有所了解。
    • 谢谢。我想我有足够的阅读量来解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    相关资源
    最近更新 更多