2012-01-06 14 views
18

Bạn sẽ làm thế nào để đăng ký các cá thể IDbConnectionFactory khác nhau trong Funq và sau đó truy cập chúng trực tiếp trong các dịch vụ của bạn? Làm trường hợp đặt tên bằng cách nào đó đi vào chơi ở đây?Cách đăng ký nhiều cá thể IDbConnectionFactory bằng Funq trong ServiceStack.net

Đây có phải là cách tiếp cận tốt nhất để thực hiện khi sử dụng các cơ sở dữ liệu khác nhau trên các dịch vụ không?

Cảm ơn!

EDIT:

Một ví dụ;). Tôi có thể là cách tắt ở đây bởi vì tôi là khá mới để IoC, nhưng nói ví dụ tôi có 2 kết nối cơ sở dữ liệu riêng biệt mà tôi muốn tiêm. Trong ServiceStack, điều này được thực hiện trong Global.asax.

container.Register<IDbConnectionFactory>(c => 
      new OrmLiteConnectionFactory(@"Connection String 1", SqlServerOrmLiteDialectProvider.Instance));            

container.Register<IDbConnectionFactory>(c => 
      new OrmLiteConnectionFactory(@"Connection String 2", SqlServerOrmLiteDialectProvider.Instance));     

Cả hai thứ này dường như được tiêm dồn dập.

Những sau đó được truy cập tự động vào cuối dịch vụ thông qua một cái gì đó như thế này:

public IDbConnectionFactory DbFactory { get; set; } 

Trong trường hợp này, nó có vẻ là đem lại cho tôi là người đầu tiên đăng ký. Tôi làm cách nào để có quyền truy cập vào một dịch vụ cụ thể ở cuối dịch vụ? Hy vọng rằng nó làm cho nó rõ ràng hơn một chút.

Dưới đây là một ví dụ đầy đủ fledged từ ServiceStack.Examples mà chỉ sử dụng 1 IDbConnectionFactory: Movies Rest

+0

Bạn có thể hiển thị một số mã không? Tôi nghĩ chúng tôi có thể cung cấp cho bạn một số mẹo về thiết kế ứng dụng của bạn, nhưng vì điều này, chúng tôi cần hiểu rõ hơn về thiết kế thực tế. Sẽ rất thú vị nếu bạn thấy những dịch vụ nào mà bạn đưa vào trong IDbConnectionFactory' và những dịch vụ đó làm gì với những phụ thuộc 'IDbConnectionFactory' đó. – Steven

+0

Lưu ý tuy nhiên Funq là một container IoC rất đơn giản (một số thậm chí có thể tranh luận nó không phải là một container IoC ở tất cả), và tất cả mọi thứ phải được dây bằng tay. Tuy nhiên, bạn có thể tiêm mọi thứ bạn muốn trong mọi dịch vụ bạn tạo. – Steven

+0

Tôi đã cập nhật câu hỏi, làm cho nó rõ ràng hơn một chút và tìm thấy bài viết của bạn trên Simple Injector. Tôi cho rằng đọc qua bây giờ với hy vọng làm sâu sắc thêm sự hiểu biết của tôi về IoC. –

Trả lời

14

Câu hỏi của tôi ở trên vẫn còn hiệu lực, nhưng sau đây có thể giúp bạn anyway.

Funq không hỗ trợ tự động xây dựng phun (a.k.a. tự động dây), và bạn sẽ phải làm điều này bằng tay bằng cách xây dựng biểu thức lambda Func<T>. Bởi vì bạn đã làm việc xây dựng tiêm bằng tay, rất dễ dàng để chọn những gì IDbConnectionFactory bạn muốn tiêm vào dịch vụ của bạn. Ví dụ:

IDbConnectionFactory yellowDbConFactory = 
    new YellowDbConnectionFactory(); 

IDbConnectionFactory blueDbConFactory = 
    new BlueDbConnectionFactory(); 

IDbConnectionFactory purpleDbConFactory = 
    new PurpleDbConnectionFactory(); 

container.Register<IService1>(c => 
    new Service1Impl(yellowDbConFactory, 
     c.Resolve<IDep1>()); 

container.Register<IService2>(c => 
    new Service2Impl(blueDbConFactory); 

container.Register<IService3>(c => 
    new Service3Impl(purpleDbConFactory, 
     c.Resolve<IDep2>()); 

Tất nhiên bạn cũng có thể được sử dụng tên đăng ký, như thế này:

container.Register<IDbConnectionFactory>("yellow", 
    new YellowDbConnectionFactory()); 

container.Register<IDbConnectionFactory>("blue", 
    new BlueDbConnectionFactory()); 

container.Register<IDbConnectionFactory>("purple", 
    new PurpleDbConnectionFactory()); 

container.Register<IService1>(c => 
    new Service1Impl(
     c.Resolve<IDbConnectionFactory>("yellow"), 
     c.Resolve<IDep1>()); 

container.Register<IService2>(c => 
    new Service2Impl(
     c.Resolve<IDbConnectionFactory>("blue")); 

container.Register<IService3>(c => 
    new Service3Impl(
     c.Resolve<IDbConnectionFactory>("purple"), 
     c.Resolve<IDep2>()); 

Do thiếu sự hỗ trợ cho tính năng tự động hệ thống dây điện, bạn sẽ kết thúc với những đăng ký khá vụng về, và điều này sẽ sớm dẫn đến một cơn ác mộng bảo trì của gốc thành phần của bạn, nhưng điều đó không liên quan đến câu hỏi của bạn ;-)

Bạn nên cố gắng ngăn ngừa sự mơ hồ trong đăng ký của mình. Trong trường hợp của bạn, bạn đã có một giao diện duy nhất, điều đó có hai thứ (kết nối với hai cơ sở dữ liệu).Trừ khi cả hai cơ sở dữ liệu chia sẻ mô hình chính xác như nhau, mỗi cơ sở dữ liệu xứng đáng giao diện riêng của mình (nếu hai ngôn ngữ này không hoán đổi cho nhau, bạn sẽ được vi phạm các Liskov substitution principle):

interface IYellowDbConnectionFactory : IDbConnectionFactory 
{ 
} 

interface IPurpleDbConnectionFactory : IDbConnectionFactory 
{ 
} 

Bởi vì các công trình cách ServiceStack, có thể bạn cần để thực hiện một triển khai thực hiện đối với từng:

class YellowDbConnectionFactory : OrmLiteConnectionFactory, 
    IYellowDbConnectionFactory 
{ 
    public YellowDbConnectionFactory(string s) : base(s){} 
} 

class PurpleDbConnectionFactory : OrmLiteConnectionFactory, 
    IPurpleDbConnectionFactory 
{ 
    public YellowDbConnectionFactory(string s) : base(s){} 
} 

Bây giờ bạn nên thay đổi định nghĩa về dịch vụ của bạn để sử dụng giao diện cụ thể thay vì sử dụng IDbConnectionFactory:

public class MovieService : RestServiceBase<Movie> 
{ 
    private readonly IYellowDbConnectionFactory dbFactory; 

    public MovieService(IYellowDbConnectionFactory factory) 
    { 
     this.dbFactory = factory; 
    } 
} 

Lưu ý rằng lớp này hiện đang sử dụng phương thức khởi tạo thay vì tiêm thuộc tính. Bạn có thể làm điều này để làm việc với việc tiêm thuộc tính, nhưng thường tốt hơn là đi kèm với việc xây dựng tiêm. Đây là một SO question về nó.

Với Funq, cấu hình của bạn sau đó sẽ trông như thế này:

container.Register<MovieService>(c => 
    new MovieService(
     c.Resolve<IYellowDbConnectionFactory>()); 

Hai giao diện mới và hai lớp và thay đổi đến MovieService không giành chiến thắng cho bạn rất nhiều, bởi vì Funq không hỗ trợ auto hệ thống dây điện. Bạn sẽ là người kết nối mọi thứ với nhau theo cách thủ công. Tuy nhiên, khi bạn chuyển sang khung làm việc thì hỗ trợ tự động đấu dây, thiết kế này cho phép vùng chứa tiêm phụ thuộc đúng mà không gặp sự cố, bởi vì không có thảo luận về nội dung cần tiêm.

+1

Cảm ơn bạn đã trả lời kỹ lưỡng. Điều này chính xác những gì tôi đang tìm kiếm. –

+5

Lưu ý: ServiceStack thực sự hỗ trợ kết nối Auto với Funq.Container của nó - xem câu trả lời của tôi. – mythz

+1

@Steven Điều gì sẽ xảy ra nếu các cơ sở dữ liệu chia sẻ cùng một mô hình? tức là Nhiều người thuê nhà –

11

Mặc dù Funq không hỗ trợ kết nối Tự động, ServiceStack thực hiện nó. Phiên bản mới nhất của ServiceStack bao gồm các quá tải Funq.Container:

container.RegisterAutoWired<T>(); 
container.RegisterAutoWiredAs<T,TAs>(); 
container.RegisterAs<T,TAs>(); 

Vì vậy, trong ví dụ của Steven bạn cũng có thể làm:

container.RegisterAs<YellowDbConnectionFactory,IYellowDbConnectionFactory>(); 

Và nó sẽ tự động đăng ký các phụ thuộc cho bạn.

+0

Khá kỳ lạ đối với việc triển khai Khung dịch vụ để có một tính năng như vậy. Điều này có vẻ như một tính năng cho một container IoC, và không cho ServiceStack. – Steven

+1

Đồng ý, tôi đã đăng bài này một thời gian dài trước đây trong danh sách gửi thư của Funq nhưng không có gì đến từ nó http://funq.codeplex.com/workitem/2158 – mythz

+2

Khung Funq dường như đã bị hủy bỏ trong một thời gian dài rồi. Tại sao bạn không chuyển sang Simple Injector làm khung công tác IoC mặc định cho ServiceStack? Vì ServiceStack có vẻ là một khung công tác hiệu năng cao, Simple Injector là một sự lựa chọn phù hợp, vì nó là khuôn khổ IoC nhanh nhất trong lĩnh vực này. Tôi nghĩ ServiceStack thực sự tốt, btw. – Steven

1

Hãy thử sử dụng mẫu Repository thay vì IoC này (điều này chỉ làm phức tạp những thứ không cần thiết). Đoạn mã trên dường như không hoạt động. Nghi ngờ một cái gì đó đã thay đổi. Tôi vẫn chưa rõ cách đăng ký IDbConnectionFactory một cách kỳ diệu sẽ điền thuộc tính IDbConnection. Sẽ yêu một số lời giải thích xung quanh này. Nếu có ai đó làm việc này bằng cách sử dụng thùng chứa ServiceClock IoC .. thì tôi rất muốn xem như thế nào. Và nó sẽ cực kỳ hữu ích để cập nhật tài liệu SS (tôi khá vui khi làm điều đó)

+0

Về IDbConnectionFactory, bạn có thể tham khảo mã ServiceStack OrmLite: public virtual IDbConnection Db {get {return this.db ?? (this.db = OrmLiteConnectionFactoryExtensions.Open (this.TryResolve ())); }} – labilbe

3

Tôi nghĩ rằng tôi sẽ kiếm được 2 xu ở đây, mặc dù tôi nhận ra câu hỏi là khá cũ. Tôi muốn truy cập vào một DB giao dịch và một DB khai thác gỗ từ ServiceStack và đây là cách tôi đã kết thúc làm việc đó từ AppHostBase Configure() phương pháp:

  container.Register<IDbConnectionFactory>(
       c => { 
        OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["MyTransactionalDB"].ConnectionString, MySqlDialect.Provider); 
        dbFactory.ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current); 
        dbFactory.RegisterConnection("LoggingDB", ConfigurationManager.ConnectionStrings["MyLoggingDB"].ConnectionString, MySqlDialect.Provider); 

        return dbFactory; 
       }); 

Theo mặc định, "MyTransactionalDB" được sử dụng khi mở một kết nối từ nhà máy, nhưng tôi có thể truy cập rõ ràng vào DB đăng nhập từ một dịch vụ qua:

 using (var db = DbFactory.Open("LoggingDB")) 
     { 
      db.Save(...); 
     }