Search Results for

    Show / Hide Table of Contents

    Component: Data migration - Working with files

    Assuming you are migrating product photos from the well-known database AdventureWorks2019. The article will show how the component handles files when migrating data.

    Step 1: Setting up the data class for storing files

    Configure a data class CwDmSampleProductPhoto for storing data migrated from the table [AdventureWorks2019].[Production].[ProductPhoto]. The files will be stored in ThumbNailPhoto and LargePhoto, which have the type Document. Don't forget to add the field CwDmLegacyId required for tracking data.

    image-20231214132416773

    Step 2: Configure a copy-data job

    Configure a copy-data job as described below:

    image-20231214133212070

    We will implement the Transform rule and the Test rule in the following steps.

    Step 3: Implement the data-transform rule

    Add a new Casewhere rule CwDm SO Migrate Product Photo:

    image-20231214133659012

    We will use IDocumentApi to store the files. Remember to check null before proceeding.

    #predicate
    var documentApi = @apiFactory.Get<IDocumentApi>();
    var item = @parameters["SourceItem"];
    
    DocumentInfo thumbnailDocInfo = null;
    if (item["ThumbNailPhoto"] != null)
    {
    	thumbnailDocInfo = documentApi.Create(item["ThumbnailPhotoFileName"]);
    	documentApi.Store(thumbnailDocInfo, Convert.FromBase64String(item["ThumbNailPhoto"].ToString()));
    }
    
    DocumentInfo largeDocInfo = null;
    if (item["LargePhoto"] != null)
    {
    	largeDocInfo = documentApi.Create(item["LargePhotoFileName"]);
    	documentApi.Store(largeDocInfo, Convert.FromBase64String(item["LargePhoto"].ToString()));
    }
    
    var data = new 
    {
    	ProductPhotoID = item["ProductPhotoID"],
    	ThumbnailPhotoFileName = item["ThumbnailPhotoFileName"],
    	ThumbNailPhoto = thumbnailDocInfo,
    	LargePhotoFileName = item["LargePhotoFileName"],
    	LargePhoto = largeDocInfo,
    	CwDmLegacyId = item["ProductPhotoID"]
    };
    
    // You can either return a DynamicDataObject or a list of DynamicDataObjects
    var migratedItem = new DynamicDataObject(new {
    	DataClassName = "CwDmSampleProductPhoto",
    	Data = data,
    	LegacyId = item["ProductPhotoID"]
    });
    return new List<DynamicDataObject>(){ migratedItem };
    

    Step 4: Implement the data-verification rule

    Add a new Casewhere rule CwDm SO Test Product Photo:

    image-20231214134140533

    Remember to log errors that fail the test.

    #predicate
    var item = @parameters["SourceItem"];
    
    var dataApi = @apiFactory.Get<IDataApi>();
    
    var filter = FilterBuilder.Create().Eq("CwDmLegacyId", item["ProductPhotoID"]).Build();
    var migratedItem = (dataApi.Search(DataObjectApiQuery
        .For("CwDmSampleProductPhoto")
        .Paging(0, 1)
        .FilterBy(filter)).Data as IList<DynamicDataObject>).FirstOrDefault();
     
    if(migratedItem == null) {
        Log.Error("CwDmSampleProductPhoto not found for {ProductPhotoID}", item["ProductPhotoID"]);
        return false;
    }
    
    if(migratedItem.Get<DocumentInfo>("ThumbNailPhoto") == null && item["ThumbNailPhoto"] != null)
    {
        Log.Error("ThumbnailPhoto is missing");
        return false;
    }
    
    if(migratedItem.Get<string?>("ThumbnailPhotoFileName") != item["ThumbnailPhotoFileName"])
    {
        Log.Error("ThumbnailPhotoFileName is not matched. Expected={Expected}. Actual={Actual}", item["ThumbnailPhotoFileName"], migratedItem.Get<string?>("ThumbnailPhotoFileName"));
        return false;
    }
    
    if(migratedItem.Get<string?>("LargePhotoFileName") != item["LargePhotoFileName"])
    {
        Log.Error("LargePhotoFileName is not matched. Expected={Expected}. Actual={Actual}", item["LargePhotoFileName"], migratedItem.Get<string?>("LargePhotoFileName"));
        return false;
    }
    
    if(migratedItem.Get<DocumentInfo>("LargePhoto") == null && item["LargePhoto"] != null)
    {
        Log.Error("LargePhoto is missing");
        return false;
    }
    
    return true;
    

    Step 5: Run and verify

    Open the job Migrate [Production].[ProductPhoto] and click Start. If everything is configured correctly, you will see batches are generated and run sequentially.

    image-20231214135058178

    In This Article
    Back to top Generated by DocFX