hhblaze / DBreeze

C# .NET NOSQL ( key value store embedded ) ACID multi-paradigm database management system.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RemoveKey - Unable to get it to work?

leedavi opened this issue · comments

HI I've got a section of code (see below) that uses RemoveKey to remove a single record from the DB.


    public void DeleteKey(string tableCode, long itemId)
    {
        using (var t = engine.GetTransaction())
        {
            t.SynchronizeTables(tableCode, "TS_" + tableCode, tableCode + "LANG");

            NBrightData nbi1 = null;
            var obj = t.Select<byte[], byte[]>(tableCode, DBreezeIdx.idx_ItemId.ToIndex(itemId)).ObjectGet<NBrightData>();
            if (obj != null)
            {
                nbi1 = (NBrightData)obj.Entity;
            }
            Console.WriteLine(nbi1.ItemId + " " + nbi1.Lang + " " + nbi1.ModifiedDate + " " + nbi1.ModuleId + " " + nbi1.ParentItemId + " " + nbi1.PortalId + " " + nbi1.Key + " " + nbi1.TableCode + " " + nbi1.TextData + " " + nbi1.UserId + " " + nbi1.XrefItemId + Environment.NewLine);

            t.RemoveKey<long>(tableCode, itemId);
            t.Commit();

            obj = t.Select<byte[], byte[]>(tableCode, DBreezeIdx.idx_ItemId.ToIndex(itemId)).ObjectGet<NBrightData>();
            if (obj != null)
            {
                nbi1 = (NBrightData)obj.Entity;
            }
            Console.WriteLine(nbi1.ItemId + " " + nbi1.Lang + " " + nbi1.ModifiedDate + " " + nbi1.ModuleId + " " + nbi1.ParentItemId + " " + nbi1.PortalId + " " + nbi1.Key + " " + nbi1.TableCode + " " + nbi1.TextData + " " + nbi1.UserId + " " + nbi1.XrefItemId + Environment.NewLine);

        }
    }

The above code runs OK, but I get the record existing before the Remove and also after...

OUTPUT


DELETE 3 -----------------------------------

3 01/01/2017 00:00:00 -1 0 1 R3 DATA text 1 0

3 01/01/2017 00:00:00 -1 0 1 R3 DATA text 1 0


I've tried multiple veriations of code with commit and table sync. But the read of the table always returns the record which should have bene removed?

In 1 situation I've have the code throw an exception, telling me the transaction doesn't exits, but the read still works and displayed the record 3.

I can't find any working examples for the RemoveKey,

Can you tell me what I'm doing wrong?

The WasRemoved flag also returns False.

commented

Start from simple operations. Put something in DB and take a look what is inside:

 using (var t = eng.GetTransaction())
            {
                t.Insert<byte[], byte[]>("t1", new byte[] { 1, 2, 3 }, new byte[] { 7 });
                t.Insert<byte[], byte[]>("t1", new byte[] { 1, 3, 4 }, new byte[] { 8 });
                t.Commit();
            }

            using (var t = eng.GetTransaction())
            {
                foreach (var row in t.SelectForward<byte[], byte[]>("t1"))
                    Console.WriteLine($"K: {row.Key.ToBytesString()}; V: {row.Value.ToBytesString()}");
            }

            using (var t = eng.GetTransaction())
            {
                t.RemoveKey<byte[]>("t1", new byte[] { 1, 2, 3 });                
                t.Commit();
            }

            Console.WriteLine("----");

            using (var t = eng.GetTransaction())
            {
                foreach (var row in t.SelectForward<byte[], byte[]>("t1"))
                    Console.WriteLine($"K: {row.Key.ToBytesString()}; V: {row.Value.ToBytesString()}");
            }

Output

K: 010203; V: 07
K: 010304; V: 08


K: 010304; V: 08

Check after insert your keys, then debug the one you delete

OK, using your code, it works.

The question is why doesn't my code, The difference I see if that I'm inserting an object, using long type as my primary key and using indexes


                bool newEntity = nbData.ItemId == 0;
                if (newEntity) nbData.ItemId = t.ObjectGetNewIdentity<long>(tableCode);

                // build Indexes
                var indexes = new List<DBreeze.Objects.DBreezeIndex>();
                var idIndex = new DBreeze.Objects.DBreezeIndex(DBreezeIdx.idx_ItemId, nbData.ItemId) { PrimaryIndex = true };
                indexes.Add(idIndex);

...
...
t.ObjectInsert(tableCode, new DBreeze.Objects.DBreezeObject
{
NewEntity = newEntity,
Entity = nbData,
Indexes = indexes
}, false);

    public void DeleteKey(string tableCode, long itemId)
    {
        using (var t = engine.GetTransaction())
        {
            t.RemoveKey<long>(tableCode, itemId);
            t.Commit();
       }
    }

All the reads for the data work OK, do I need to do something different for RemoveKey and objects?

commented

First of all you advice to understand how object layer works and take a look what is in the table after your object insert using standard

using (var t = eng.GetTransaction())
{
foreach (var row in t.SelectForward<byte[], byte[]>("t1"))
Console.WriteLine($"K: {row.Key.ToBytesString()}; V: {row.Value.ToBytesString()}");
}

And yes, to remove object completely you may use tran.ObjectRemove.

OK, Just found the ObjectRemove option, I'll give it a go now! thx!

commented

actually you can use RemoveKey to remove single record representing index, just take a look how DBreeze stores your data to understand it

OK the objecrremove works for 2 tables..

    public void DeleteKey(string tableCode, long itemId)
    {
        using (var t = engine.GetTransaction())
        {
            t.ObjectRemove(tableCode, DBreezeIdx.idx_ItemId.ToIndex(itemId));
            t.Commit();

            t.ObjectRemove("TS_" + tableCode, DBreezeIdx.idx_ItemId.ToIndex(itemId));
            t.Commit();

            var l = GetListByParentItemId(tableCode + "LANG", itemId);
            foreach (var r in l)
            {
                t.ObjectRemove(tableCode + "LANG", DBreezeIdx.idx_ItemId.ToIndex(r.ItemId));
                t.Commit();
            }

        }
    }

But the loop on the "LANG" field, which is trying to remove localized data linked to the base record, throws an error saying the transaction not longer exists. Have you any idea why?

commented

try to use one commit in the end of transaction... don't use it after every operation

OK, solved it.

For some reason the Generic foreach loop on the object was causing the problem.
I've removed the generic loop and used a selectforwardFromTo method and it works!!!

    public void DeleteKey(string tableCode, long itemId)
    {
        using (var t = engine.GetTransaction())
        {

            t.ObjectRemove(tableCode, DBreezeIdx.idx_ItemId.ToIndex(itemId));
            t.ObjectRemove("TS_" + tableCode, DBreezeIdx.idx_ItemId.ToIndex(itemId));

            foreach (var el in t.SelectForwardFromTo<byte[], byte[]>(tableCode + "LANG", DBreezeIdx.idx_ParentItemId.ToIndex(itemId, long.MinValue), true, DBreezeIdx.idx_ParentItemId.ToIndex(itemId, long.MaxValue), true))
            {
                t.ObjectRemove(tableCode + "LANG", DBreezeIdx.idx_ItemId.ToIndex((long)el.ObjectGet<NBrightData>().Entity.ItemId));
            }

            t.Commit();
        }
    }

I presume that the generic list is setting a reference to the DB object? and hence removing it causes an issue? Have you got any deeper knowledge of why the DB refused to delete with a generic list taken with only a read method?

And the more worrying question is will this cause any issue on a standard application?
I would have expected the population of a generic list NOT to lock or cause any influence on the DB actions?

commented

I think in DBreeze should be no similar problems, but to answer your question I need emulating insert/delete code and a bit of time.

OK, I'm building a generic wrapper provider for DBreeze, to deal with my type of data. Once I have something working I'll post it on GitHub and you can hopefully point out improvements and errors.