Manoj Kumawat
+3
Feb 27, 2023
visibility 3071
star star star star star
(2 votes)

Deleting missing metafields in code programmatically

This blog post will help you in deleting meta fields programatically in catalogue context. We will only delete metafields which are user generated and missing from code (deleted later in the code) but remain in database. 

#1 - get the list of metaclasses (user generated) 

    private readonly Mediachase.MetaDataPlus.Configurator.MetaClassCollection _metaClassCollection;

    _metaClassCollection = Mediachase.MetaDataPlus.Configurator.MetaClass.GetList(CatalogContext.MetaDataContext, true);

    _metaClassCollection.Cast<Mediachase.MetaDataPlus.Configurator.MetaClass>()
                .Where(c => c.IsUser
                && c.MetaFields.Any(x => x.IsUser))

The above collection will fetch meta classes created by the user and any of it's metafields is user generated at least. 

#2 - Getting metafields for class

     metaClass.MetaFields
     .Where(c => c.IsUser && c.OwnerMetaClassIdList.MetaCollectionHasOnly(id))

Above code snippet selects all the meta fields for a metaclass and makes sure it is not fetching any other metafield under a class which comes from relation of the same class (i.e. product > Category > Catalog)
Therefore, It only displays meta fields strictly which are part of the class. I've used an extension method that makes sure each metafiled has only 1 exact same parent as current class. 

 public static bool MetaCollectionHasOnly(this MetaClassIdCollection collection, int classId)
    {
        try
        {
            if (collection != null && collection.Count == 1)
            {
                return collection[0] == classId;
            }

            return false;
        }
        catch
        {
            //we don't want to catch exception in this case.
            return false;
        }
    }

Now it comes to the final step which is most important - Identify missing field from class

Each metaclass is mapped with contentType class you have in your code. Here we need to figure out which class in code is mapped with metaclass in database. Let's understand it easy way -

If I have a base class for all the products in the code as ProductBase with [CatalogContentType] decorator then for MetaClass Product MetaClassToContentTypeMap will fetch ProductBase.

Now the only thing you need to check if the metafield exists in the code as follows - 

private readonly Injected<MetaClassToContentTypeMap> _contentTypeModelRepository;

public string MetaFieldName { get; set; }
private Type ClassType
    {
        get
        {
            return _contentTypeModelRepository.Service.GetContentTypeModel(MetaClassId);
        }
    }

    public bool IsAvailable 
    {
        get
        {
            return ClassType.HasProperty(this.MetaFieldName);
        }
    }

IsAvailable property returns whether the metafield exists in the code or not. 

--------------------------------------------------------------

Update - Deleting what we have detected so far. In my project I had an endpoint which would do it for me. The field you want to delete, send it along with it's parent classId. 

 [HttpPost]
    [Route("metafields/{classId}/delete/{fieldId}", Name = "DeleteMetaField")]
    public JsonResult Delete(int classId, int fieldId)
    {
        var result = false;

        try
        {
            var metaClass = _metaClassCollection.Cast<Mediachase.MetaDataPlus.Configurator.MetaClass>()
                .FirstOrDefault(c => c.Id.Equals(classId));

            if (metaClass != null)
            {
                var metaField = metaClass.MetaFields.FirstOrDefault(c => c.Id.Equals(fieldId));
                metaField.Delete();
            }

            result = true;
        }
        catch (Exception ex)
        {
            Log.Error("Failed to delete" + ex.Message);
            result = false;
        }
        return new JsonResult(result);
    }

And the extension method to delete: 

public static class MetaFieldExtensions
{
    private static readonly MetaDataContext Context = CatalogContext.MetaDataContext;

    public static void Delete(this MetaField metaField)
    {
        if (metaField == null)
        {
            return;
        }
        foreach (var metaClassId in metaField.OwnerMetaClassIdList)
        {
            var cls = Mediachase.MetaDataPlus.Configurator.MetaClass.Load(Context, (int)metaClassId);
            cls.DeleteField(metaField);
        }

        MetaField.Delete(Context, metaField.Id);
    }
}

Hope this helps. 

Feb 27, 2023

Comments

Marcin
Marcin Apr 7, 2023 09:26 AM

@Manoj 

Thanks for the article. In the title I see "Deleting missing metafields in code programmatically", but from the article I only learned how to detect properties that are still in the database, but not in the code. Could you extend the article with more information on how to get rid of such unused properties?

In my case, after using Commerce for a long time, I am dealing with properties that are not used - sometimes they are single, sometimes there are more. I would like them not to be displayed as well as get rid of them from the database to speed up the performance of the products - currently, by handling existing obsolete properties, the products seem to run slower.

Manoj Kumawat
Manoj Kumawat Apr 20, 2023 07:47 AM

Marcin, Just updated it. Hope it helps!

error Please login to comment.
Latest blogs
Automated Search & Navigation to Graph Migration with Claude Code

A Claude Code plugin that scans your S&N codebase, applies Graph SDK transformations, and validates the result. Install once, run one command. CMS ...

Connor Fortin | Jun 24, 2026

Migrating from Find to Graph: Lessons Learned from a Real CMS 13 Project

While migrating a search solution from Optimizely Search & Navigation (Find) to Optimizely Graph in CMS 13, I encountered several issues that were...

Binh Nguyen Thi | Jun 24, 2026

Optimizely: Upgrade Opti-ID and .NET 10 in CMS 12

Many Optimizely customers are planning their roadmap around a future migration to Optimizely CMS 13. As a result, upgrades such as Opti ID adoption...

Madhu | Jun 23, 2026 |

Understanding Optimizely Graph: Caching, Webhooks & Avoiding Stale Content (Optimizely SaaS CMS)

📌 Scope: This post covers Optimizely CMS (SaaS) only — using the official @optimizely/cms-sdk and @optimizely/cms-cli packages with Next.js 15. If...

Kiran Patil | Jun 23, 2026 |