不确定如何使用依赖注入 +存储库模式 + WinForm 应用程序的工作单元模式

发布于 2024-08-22 17:33:24 字数 3070 浏览 8 评论 0原文

(对文字墙表示歉意...:) )

摘要

在我的 Winfor 应用程序中使用依赖注入正在创建大量存储库上下文。我不确定我使用它的方式是对还是错,或者常见的做法是什么。

详细信息

在过去的 6 个多月里,我一直在制作 ASP.NET MVC 应用程序,这些应用程序通过存储库模式实现了工作单元模式。除此之外,我一直在所有这些 Web 应用程序上使用依赖注入,并取得了一些成功。

这是我连接存储库的一个示例。

public EntityFrameworkRepositoryRegistry() 
{ 
    For<IUnitOfWork>() 
            .HybridHttpOrThreadLocalScoped() // Lifecycle of the object.
            .Use<SqlServerContext>()  // My EF Context.
            .Ctor<string>("connectionString").Is("name=SqlServer_EF")
            .Ctor<string>("defaultContainerName").Is("Entities"); 
 
    // Ayende's EFProf application :) 
    EntityFrameworkProfiler.Initialize();      

    Scan(x => 
        { 
            x.TheCallingAssembly(); 

            x.ExcludeNamespaceContainingType<Fake.FakeContext>(); 

            x.WithDefaultConventions(); 
        } 
    );    
} 

好的 - 效果很好。 这里要注意的主要一点是,

  • 我假设生命周期对于 Web 场景来说是正确的。
  • 上下文只会存在一次,每个请求命中 网络服务器。

kewl。

现在,对于我的 WinForm 应用程序,我最初创建了一个 工作单元对象(还没有依赖注入)并不断将该婴儿传递给 所有服务(然后到存储库)。

对于这个 win 应用程序,它会访问数据库以查找所有文本 它需要解析的文件。 (例如 25 个文件)。然后,对于每个文件, 创建一个新的解析器,读取每一行并将解析后的数据放入 一个数据库表。美好的。

问题是,这个概念在所有解析器之间共享,这 整个商店都出现了严重的错误。

然后我添加了一些依赖注入并使用上面的注册表代码。类似的事情——很多严重的错误。这是因为再次为单线程创建了一个上下文 ->的winform。

因此,我现在将上下文注册表调整为以下内容:-

public EntityFrameworkRepositoryRegistry(bool isForTheWeb) 
{ 
    if (isForTheWeb) 
    { 
        For<IUnitOfWork>() 
            .HybridHttpOrThreadLocalScoped() 
            .Use<SqlServerContext>() 
            .Ctor<string>("connectionString").Is("name=SqlServer_EF") 
            .Ctor<string>("defaultContainerName").Is("Entities"); 
    } 
    else 
    { 
        For<IUnitOfWork>() 
            .Use<SqlServerContext>() 
            .Ctor<string>("connectionString").Is("name=SqlServer_EF") 
            .Ctor<string>("defaultContainerName").Is("Entities"); 
    } 
    
    EntityFrameworkProfiler.Initialize(); 
    
    Scan(x => 
    { 
        x.TheCallingAssembly(); 
        
        x.ExcludeNamespaceContainingType<Fake.FakeContext>(); 
        x.WithDefaultConventions(); 
    }); 
} 

因此,对于 WinForm 应用程序,它现在不设置生命周期。这 然后创建了大约 160 个左右的上下文,我认为! (但其实并没有 错误,要么)。

所以,我不确定这是否是正确的做事方式。

所以我的应用程序实际上有 25 个不同的计时器来检查文件 每.. 说.. 10 秒。如果有新数据,它会解析它。 否则,请在 10 秒后返回。

这些被解析的文件中的每一个都应该是它自己的线程吗? 然后为每个线程创建一个上下文? (我觉得类似于 网络场景)。或者这样可以吗?我知道这有很多背景,但是 每个上下文并不意味着与数据库的实时连接..并且 连接池,这应该不是问题。

它之所以有如此多的上下文,是因为以下原因 代码...(这些是一些单独的构造函数 存储库类...)

public SqlServerContext(string, string); 
public GameFileRepository (IUnitOfWork); 
public LogEntryRepository(IUnitOfWork); 
public AlertRepository(IUnitOfWork); 
... etc.. 

以及主服务...

public PunkBusterParser(IUnitOfWork, IGameFileRepositry, 
ILogEntryRepository, ILoggingService); 

因此该服务需要一个 UoW 并且每个存储库也需要 一个..这意味着正在为每个创建一个新的。

我确信我的结构不正确...

任何建议将不胜感激!

(apologies for the Wall Of Text... :) )

Summary

Using Dependency Injection with my Winfor application is creating a large number of Repository Context's. I'm not sure if the way i'm using this is right or wrong, or what the common practice is.

Details

In the last 6 odd months, I've been making ASP.NET MVC applications that impliment the Unit O fWork pattern with the Repository Pattern. On top of this, I've been using an Dependency Injection on all of these web applications with some success.

So this is an example of me wiring up my repository.

public EntityFrameworkRepositoryRegistry() 
{ 
    For<IUnitOfWork>() 
            .HybridHttpOrThreadLocalScoped() // Lifecycle of the object.
            .Use<SqlServerContext>()  // My EF Context.
            .Ctor<string>("connectionString").Is("name=SqlServer_EF")
            .Ctor<string>("defaultContainerName").Is("Entities"); 
 
    // Ayende's EFProf application :) 
    EntityFrameworkProfiler.Initialize();      

    Scan(x => 
        { 
            x.TheCallingAssembly(); 

            x.ExcludeNamespaceContainingType<Fake.FakeContext>(); 

            x.WithDefaultConventions(); 
        } 
    );    
} 

Ok - works great.
Main thing to note here is that

  • I'm assuming the Lifecycle is the correct one for a Web scenario.
  • The context will only exists once, per REQUEST that hits the
    webserver.

kewl.

Now, for my WinForm application, i initially created a single
Unit Of Work object (no dependency injection, just yet) and kept passing that baby around to
all the services (and then to the repositories).

For this win application, it hits the DB to find out all the text
files it needs to parse. (eg. 25 files). Then, for each file, it
creates a new Parser, reads each line and chucks the parsed data into
a db table. Fine.

Problem was, this concext was being shared amoungst ALL Parsers, which
was seriously throwing up errors all over the shop.

So then i added some Dependency Injection and uses that registry code above. Sorta same thing - lots of serious errors. This is because ONE context was again created for the single thread -> the winform.

So, i now tweaked the Registry of the Context to following :-

public EntityFrameworkRepositoryRegistry(bool isForTheWeb) 
{ 
    if (isForTheWeb) 
    { 
        For<IUnitOfWork>() 
            .HybridHttpOrThreadLocalScoped() 
            .Use<SqlServerContext>() 
            .Ctor<string>("connectionString").Is("name=SqlServer_EF") 
            .Ctor<string>("defaultContainerName").Is("Entities"); 
    } 
    else 
    { 
        For<IUnitOfWork>() 
            .Use<SqlServerContext>() 
            .Ctor<string>("connectionString").Is("name=SqlServer_EF") 
            .Ctor<string>("defaultContainerName").Is("Entities"); 
    } 
    
    EntityFrameworkProfiler.Initialize(); 
    
    Scan(x => 
    { 
        x.TheCallingAssembly(); 
        
        x.ExcludeNamespaceContainingType<Fake.FakeContext>(); 
        x.WithDefaultConventions(); 
    }); 
} 

So for a WinForm application, it now doesn't set the Lifecycle. This
then created around 160 or so context's i think! (But it didn't really
error, either).

So, i'm not sure if this is the right way to do things.

So my app, in effect, has 25 different timers going, to check a file
every .. say .. 10 secs. If there's new data, it parsers it.
Otherwise, come back in 10 secs.

Should each one of these files that gets parsed, be it's own thread?
and then create a context per thread? (which i feel is similar to the
web scenario). Or is this fine? I know it's a lot of context's, but
each context doesn't mean a live connection to the db .. and with
connection pooling, this shouldn't really be a problem.

The reason it has so many contexts, is becuase of the following
code... (and these are seperate Constructors for some of the
Repository classes...)

public SqlServerContext(string, string); 
public GameFileRepository (IUnitOfWork); 
public LogEntryRepository(IUnitOfWork); 
public AlertRepository(IUnitOfWork); 
... etc.. 

and for the main Service...

public PunkBusterParser(IUnitOfWork, IGameFileRepositry, 
ILogEntryRepository, ILoggingService); 

so the service requires an UoW and each repository also requires
one ..which means a new one is getting created for each one.

I'm sure i haven't structured this correctly...

Any suggestions would be sincerely grateful!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枕头说它不想醒 2024-08-29 17:33:24

Ayende 的这篇文章可能会为您提供一些有关如何在桌面应用程序中管理工作单元的见解(总体思路是使用“每个演示者的会话”): com/en-us/magazine/ee819139.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

This article by Ayende might provide you with some insight about how to manage your unit of work in a desktop application (The general idea is to use a 'session per presenter') : http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文