I am doing move data from old version to new version base on nopcommerce

redis as message queue for micro services and event sourcing

The basic ideas:
- use redis as center server pubsub and message queue.
- type of object will become an channel in redis
- every change for object will published to subcribers to process
- worker (process business) work as the chain in factory
- work follow of states object become sequence of type's object

We seperate read side and write side to data storage
- frontend only read, push command want to change data
- in view of deployment => more security cause:
--- frontend just read only. 
--- business can run locally or everywhare
- lack of system all depend on redis server(s) but redis very good in distributed and fast, reliable. 

We seperate bussiness (often write side) into more than one worker to do.
Support one-one-process by-publish-subscribe
- object store in redis queue. subscribers (worker) will dequeue to process
Support one-many-process by-publish-subscribe
- object store in redis channel. subscribers will get broadcast to process

source code c#



Code structor

Core: IDistributedServices and redis services to pubsub command and data
DataAccess: code first entity framework. real data storage manipulate.
Domain: defind entity and data model for whole solution. shared from top to bottom
Repository: the engine to subcribe change of entity to make change by call DataAccess (write side) console app
Services: the engine to subcribe change of datamodel to subscribe change of data, do business then expose to entities then push to RepositoryEngine. (write side). this engine does not know about DataAccess,Repository,SampleWeb-frontend 
It just work with DistributedCommand (entitycommand, datamodelcommand...) to do business. it listent frontend, and push command to repository engine.
SampleWeb:  the front end, (read side) use DataAccess with permission readonly (select sql statement) then push command (command entity, command datamodel)

  public interface IDistributedServices
        void Publish<T>(DistributedCommand<T> cmd) where T : class;
        void Subscribe<T>(Action<string, DistributedCommand<T>> callBack) where T : class;

        void PublishEntity<T>(DistributedCommandEntity<T> cmd) where T : class, IEntity;
        void SubscribeEntity<T>(Action<string, DistributedCommandEntity<T>> callBack) where T : class, IEntity;

        void PublishDataModel<T>(DistributedCommandDataModel<T> cmd) where T : class, IDataModel;
        void SubscribeDataModel<T>(Action<string, DistributedCommandDataModel<T>> callBack) where T : class, IDataModel;

    public class DistributedCommand<T> where T : class 
        public CommandBehavior CommandBehavior { get; set; }

        public T Data { get; set; }

        public Type DataType { get { return Data.GetType(); } }

        public DistributedCommand(T data,  CommandBehavior commandBehavior = CommandBehavior.Queue)
            Data = data;
            CommandBehavior = commandBehavior;

        public string ToJson()
            return JsonConvert.SerializeObject(this);

        public DistributedCommand<T> FromJson(string json)
            return JsonConvert.DeserializeObject<DistributedCommand<T>>(json);