System consuming WCF services from another system,

2019-07-12 04:48发布

问题:

This is an issue that I have struggled with in a number of systems but this one is a good example. It is to do with when one system consumes WCF services from another system, and each system has their own database, but there are relationships between the two databases.

We have a central database that holds a record of all documents in the company. This database includes Document and Folder tables and it mimicks a windows file structure. NHibernate takes care of data access, a domain layer handles logic (validating filenames/no identical filenames in the same folder etc.) and a service layer sits on that, with services named 'CreateDocument(bytes[])', 'RenameDocument(id, newName) ', 'SearchDocuments(filename, filesize, createdDate)' etc. These services are exposed with WCF.

An HR system consumes these services. The HR database has a separate database that has foreign keys to the Document database: it contains an HRDocument table that has a foreign key DocumentId, and then HR specific such as EmployeeId and ContractId.

Here are the problems amonst others:

1) In order to save a document, I have to call the WCF service to save it to the central db, return the ID and then save to the HRDocument table (along with the HR specific information). Because of the WCF call and all Document specific data access being done within the Document application, this can't be done all within one transaction, resulting in a possible loss of transaction integrity.

2) In order to search on say, employeeId and createdDate, I have to call the search service passing in the createdDate (Document database specific fields) and then search the HRDocument database on the Id's of the returned records to filter the results returned. This feels messy, slow and just wrong.

I could duplicate the NHibernate mapping files to the Document database in the DAL of the HR application. This means I could specify the relationship between HRDocument and Document. This means I could join the tables and search like that but would also mean I would have to duplicate domain logic and violate the DRY principle, and all that entails.

I can't help feeling I'm doing something wrong here and have missed something simple.

回答1:

I recommend you to apply CQRS and Event Driven Architecture principles here

    • Use Guids as primary keys - then you will be able to generate primary key for document and pass it to WCF
      method call.
    • Use messaging on other side of WCF service to prevent data loss (in case of database failure and
      something like that).
    • Remove constaints between databases - immediate consistent applications don't scale. Use eventual consistency paradigm instead.
  1. Introduce separate data storage for reads purpose that contains denormalized data. Then you will be able to do search very easy. To ensure consistency in your read storage (in case when Document creation failed) you could implement some simple workflow (saga in terms of CQRS)



回答2:

You can create a common codebase which will include base implementation of Document along with all the mappings, base Domain Model etc.

A Document Service and an HR System use the same codebase. But in HR System you extend base Document class (or classes) with your HRDocument using inheritance mapping strategy which will suit your needs the best.

public class HRDocument : Document 

And from HR System you don't even have to call Document Service anymore, you just use NH and enjoy ACID and all that. But Document Service is still there and there's no code duplication.