circles-arrows / blueprint41

An Object Graph Mapper for CSharp to connect to Neo4j or Memgraph.
http://www.blueprint41.com/
MIT License
31 stars 8 forks source link

How to put unique constraints for multiple properties? #62

Open PalashKarmaker opened 5 months ago

PalashKarmaker commented 5 months ago

Please let us know how to put unique constraints for multiple properties. I can't see any option other than Add property in Data store to add uniqueness, which holds true for only single property.

circles-arrows commented 5 months ago

There is no officially supported way to do this for constraints with multiple properties, at least not for now.

Though there is a fairly good workaround you could do to support these type of constraints in your data model. The trick is that Blueprint41 does not support constraints of this type, but also doesn't try to micro manage them. If you added the constraint manually, Blueprint41 will not touch this type of constraint when it's managing the supported Unique constraints.

This comes with a few caveats though: 1) If/when Blueprint41 will get support this type of constraints in the future, this hack will stop working. By that time the constraint will be automatically removed, unless if you add it to the model in the (by then) officially supported manner. 2) This hack only works with Neo4j and not with Memgraph, since Memgraph does not support constraints for multiple properties and Blueprint41.MemgraphDriver is implemented differently.

    [Version(..., ..., ...)]
    public void HackCompositeConstraint()
    {
        // Run a data migration if a real database is connected, this is not part of the managed schema.
        DataMigration.Run(delegate ()
        {
                // Instead of managing data, we write the constraint directly in the graph.
                DataMigration.ExecuteCypher("CREATE CONSTRAINT [CONSTRAINT_NAME_HERE] FOR (node:[LABEL_HERE]) REQUIRE (node.[FIELD_HERE], node.[FIELD_HERE]) IS UNIQUE");
        });
    }

You could add some code to your StartUp() to warn you when Bluerpint41 gets proper support for this feature:

    MyModel model = new MyModel()
    model.Execute(true);

#if DEBUG
    using (Transaction.Begin())
    {
        if (!Transaction.Current.Run("show constraints").Select(item => item.Values["name"]?.ToString()).Any(item => item == "[CONSTRAINT_NAME_HERE]"))
            throw new NotSupportedException("REMINDER!!! BP41 now supports constraints for multiple properties, plz add them to the model the proper way.");
    }
#endif

Hope this solves your problem for now!