orchardcmsorchardcms-1.10

Load catalogs from external DB and link them to ContentParts as ContentRecords


Example: I have a countries catalog stored in another DB and I need to use it as a property in some ContentParts. I'm trying to make the connection without interfering much with Orchard wiring.

public class MoviePart : ContentPart<MoviePartRecord>
{
    public IEnumerable<CountryRecord> Countries
    {
        get
        {
            return Record.Countries.Select(r => r.CountryRecord);
        }
    }
}

The relation between CountryRecords and MovieParts will be on the Orchard DB, but the CountryRecord data is in another DB. I only need Read access, but I don't get which and how to override the Handler to use the other source.

Do I need to create a ContentHandler and override all methods, and create another StorageFilter that uses the new repository with the external source? And how would I inject the new repo into the handler?

public class CountryPartHandler : ContentHandler
{
    public CountryPartHandler(IRepository<CountryPartRecord> repository)
    {
        Filters.Add(StorageFilter.For(repository));
    }

    protected override void Loading(LoadContentContext context)
    {
        base.Loading(context);
    }
}

Update:

In this Using External Data with Orchard (around 25th min) video, he seems to be doing what I need with this code:

public ProductPartHandler(IRepository<ProductPartRecord> repository, Work<IProductService> productServiceWork)
    {
        Filters.Add(StorageFilter.For(repository));

        OnActivated<ProductPart>((context, part) => {
            part.ProductField.Loader(() => productServiceWork.Value.GetProduct(part.Id));
        });
    }

But in my code it can't find the "Loader" function, even though I have all the references from the video too, so maybe ProductField is a custom type?


Solution

  • So that is a lazy field on the part, something like this:

    public class MyPart : ContentPart {
        internal readonly LazyField<CustomData> CustomDataField = new LazyField<CustomData>();
    
        public CustomData CustomData {
          get { return CustomDataField.Value; }
        }
    }
    
    public class CustomData {
        ...
    }
    
    public class MyPartHandler : ContentPartHandler {
    
       private ICustomService _customService;
    
       public MyPartHandler(ICustomService customService){
          _customService = customService;
          OnActivated<MyPart>(Initialize);
       }
    
       private void Initialize(ActivatedContentContext context, MyPart part){
             part.CustomDataField.Loader(() => {
                 return _customService.Get(part.ContentItem.Id);
             });
       }
    }
    

    I don't know how you are loading your external data, whether via rest, wcf etc., but the logic can just be thrown into the custom service