Menu

Berkeley DB API for Visual Basic .NET 2.0

Help
2007-09-25
2013-04-09
1 2 > >> (Page 1 of 2)
  • Adair Vargas

    Adair Vargas - 2007-09-25

    I had problems implementing this API in Visual Basic, and i had to modify the C# version of the api to work in VB.NET. The major problems are the ambiguous type (DB and Db) and the way the Serialize and Deserialize methods are declared, because VB.NET can't figure which to use in which case. The way I take out this problems was renaming the methods and the Db statement. If any ones wants a version ready to build, send me an email. I will kep an eye in this project, and if the owner of the project wants, publish the vb.net version here.

     
    • Karl Waclawek

      Karl Waclawek - 2007-09-26

      Hi Adair,

      I am interested in your modifications, as I would like the API to be usable from VB without changes.
      If you could send me a diff, or a list of things you did then I may be able to incorporate them in some way into the C# code.

      I understand that VB is not case sensitive, so I should have remembered that when defining the API.
      Also, could you explain the Serialize issues - my VB days are so far back that I barely remember it.

      Karl

       
    • Adair Vargas

      Adair Vargas - 2007-09-26

      Ok, the changes are not already maked or listed, because I still don't use all the functions of the API, so i will keep updating if theres is another changes. The ones I made so far are:

      -Changed the Db type to Database, in the examples you dont declare a database of type Db, now I declare of type Database.

      -The serialization issues are mainly caused for VB.NET IDE, because can't figure wich type of serializer/deserializer to use. For example, I converted the examples to VB.NET using the Sharp Develop's Converter (a good one to convert entire projects in one step), and when converted, in the serialize part, VB.NET give to me an error saying "string don't fullfill the requirement of Type struct in the serialize(of T)", and in the deserialize part, one saying "Integer don't fullfill the requirement of type class in the deserialize(of T)", here, I only renamed the metods to let VB.NET know which one to use, But still the names are provisional.

      I sill don't use the FromDBEntry and ToDBentry methods of the formater, and I imagine i need to change this. I will kep you updated of any other change needed.

      Adair

       
    • Adair Vargas

      Adair Vargas - 2007-09-26

      I forgot to say that there is in fact, the C# version can be used in the way is writed now. I'm working in a generic class that simulate some structures in provided by the framework, like the hashtable, but with a DB in BerleyeDB. I this case, I need to use the serialize and deserialize functions in the way that are now (same name, but diferent fuction inside). So maybe we need to keep the to versions alive.

       
    • Karl Waclawek

      Karl Waclawek - 2007-09-26

      I did one thing in my source, I renamed DB to DB_ and left Db as it is. That way we have no name conflict, and both show up in VB.NET. I think that should work and also requires no change to the public API (the DB_ struct should normally not be used anyway).

      About the Serialize() issue: Are you saying that the compiler can handle it, but the IDE gets confused?

       
    • Adair Vargas

      Adair Vargas - 2007-09-26

      Ok, the change in the Db and DB is ok.

      The issue in the serialize is that both the compiler and the IDE (mainly because we tried to compile it using the Framework SDK without IDE) can't figure wich one to use, actually, VB don't supor the Where statement in the serialize declaration (it appears VB ignore this or take wathever it wants). Even when the where declares struct or class.

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-26

        Well, I declared the serialization Dll as CLS compliant, so it should work with VB.
        Can you send me a small demo app that has the problem?

        Thanks,

        Karl

         
    • Adair Vargas

      Adair Vargas - 2007-09-26

      Ok, I'll send you an example (one of your demos in a VB.Net conversion), but can you give me your file so i can Send you the entire project.

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-26

        OK, my e-mail is karl at waclawek.net (replace the 'at).

         
    • Adair Vargas

      Adair Vargas - 2007-09-27

      I sent the example to your email. I managed to convert my classes to c#, and i still get the error of the serialize and in the toDBentry. the ide Give to me this error: The type 'TData' must be a reference type in order to use it as parameter 'T' in the generic type or method 'BerkeleyDb.Serialization.BdbFormatter.ToDbEntry<T>(T)'

      This is my code:

      public bool Add<TKey,TData>(ref TKey  KeyString,ref  TData  StringValue)
                  where TKey :class
                  where TData : struct
                          {

                  DbEntry key = m_fmt.ToDbEntry<TKey >(KeyString);
                  DbEntry data = m_fmt.ToDbEntry<TData >(StringValue);

                  try
                  {
                      myObject.PutNew(null, ref key, ref data);
                      RecordCount += 1;
                  }
                  catch (BerkeleyDb.BdbException ex)
                  {

                      throw new FinamexDBException("Imposible adicionar registro", ex);

                  }

                  return System.Convert.ToBoolean(WriteStatus.Success);

              }

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-27

        Hard to tell - are you using your build of the serialization assembly, or my build?

         
      • Karl Waclawek

        Karl Waclawek - 2007-09-27

        It took me a while, but the solution is this:

          DbEntry data = m_fmt.ToDbEntry<TData >(ref StringValue);

        Without the ref it does not match the signature of ToDbEntry for struct parameters!

         
    • Adair Vargas

      Adair Vargas - 2007-09-27

      I solved this one, but i get another with a deserialize. The code looks  like this:

      public TData  GetValue<TKey, TData>(TKey  KeyString)
                   where TKey : class
                  where TData : struct
              {
                  byte[] tempBuffer = new byte[1025];

                  DbEntry key = m_fmt.ToDbEntry<TKey >(KeyString);
                  DbEntry data = DbEntry.Out(tempBuffer);

                  ReadStatus status;

                  try
                  {
                      status = myObject.Get(null, ref key, ref data, BerkeleyDb.DbFile.ReadFlags.None);
                  }
                  catch (BerkeleyDb.BdbException ex)
                  {
                      status = ReadStatus.NotFound;
                      throw new FinamexDBException("Imposible obtener registro", ex);

                  }

                  if (status == ReadStatus.Success)
                  {

                      TData  Result = default(TData ) ;
                      m_fmt.InitDeserialization(data.Buffer, data.Start);

                      try
                      {
                          m_fmt.Deserialize<TData >(ref Result);
                      }
                      catch (BerkeleyDb.BdbException ex)
                      {
                          throw new FinamexDBException("Imposible desserializar texto", ex);
                      }

                      return Result;
                  }

                  else
                  {

                      return default(TData );

                  }
              }

      The error text is this one: The type 'TData' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Kds.Serialization.Formatter<F>.Deserialize<T>(ref T)'

       
    • Adair Vargas

      Adair Vargas - 2007-09-27

      Sorry Karl, but i poste the wrong code for my promblem, the right one is:

      public TData  GetValue<TKey, TData>(TKey  KeyString)
                   where TKey : class
                  where TData : struct
              {
                  byte[] tempBuffer = new byte[1025];

                  DbEntry key = m_fmt.ToDbEntry<TKey >(KeyString);
                  DbEntry data = DbEntry.Out(tempBuffer);

                  ReadStatus status;

                  try
                  {
                      status = myObject.Get(null, ref key, ref data, BerkeleyDb.DbFile.ReadFlags.None);
                  }
                  catch (BerkeleyDb.BdbException ex)
                  {
                      status = ReadStatus.NotFound;
                      throw new FinamexDBException("Imposible obtener registro", ex);

                  }

                  if (status == ReadStatus.Success)
                  {

                      TData  Result = default(TData ) ;
                      m_fmt.InitDeserialization(data.Buffer, data.Start);

                      try
                      {
                          m_fmt.Deserialize<TData >(ref Result);
                      }
                      catch (BerkeleyDb.BdbException ex)
                      {
                          throw new FinamexDBException("Imposible desserializar texto", ex);
                      }

                      return Result;
                  }

                  else
                  {

                      return default(TData );

                  }
              }

      and the problem is :

      The type 'TData' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Kds.Serialization.Formatter<F>.Deserialize<T>(ref T)'   

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-27

        The problem is similar to the other problem.
        There are three signatures for deserializing a single instance:

            public T? Deserialize<T>() where T: struct

            public void Deserialize<T>(ref T value, out bool isNull) where T: struct

            public void Deserialize<T>(ref T obj) where T: class

        Your call matches the third one, but you are using a struct type.
        However, since deserialization can return null, we need to deal
        with it differently for structs. We have two choices, use a nullable
        struct (first signature), or return a second boolean value, isNull.

        Karl

         
    • Adair Vargas

      Adair Vargas - 2007-09-27

      I made it, but now, i have a question: How can i make this to work with a structure of this type:

      Public Structure Valores
          Public i As String
          Public t As String
      end strucutre

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-27

        This should work:

          struct Valores {
            public string i;
            public string t;
          }

          public class ValoresField: ValueField<Valores>
          {
            public ValoresField(Formatter fmt, bool isDefault) : base(fmt, isDefault) { }

            protected override void DeserializeValue(ref Valores value) {
              Fmt.Deserialize<string>(value.i);
              Fmt.Deserialize<string>(value.t);
            }

            protected override void SerializeValue(ref Valores value) {
              Fmt.Serialize<string>(value.i);
              Fmt.Serialize<string>(value.t);
            }

            protected override void SkipValue() {
              if (Fmt.Skip<string>())
                Fmt.Skip<string>();
            }
          }

        Better explanation is in the docs.

        Karl

         
        • Karl Waclawek

          Karl Waclawek - 2007-09-27

          Sorry, small correction:

                Fmt.Deserialize<string>(ref value.i);
                Fmt.Deserialize<string>(ref value.t);

          Karl

           
    • Adair Vargas

      Adair Vargas - 2007-09-27

      Ok, i Got an Idea an is working!!!!. Actually I'm Using the same Version of the API for my C# code and the VB.NET code. I made a more radical modification in te library (One must be the DB and Db change). I declared 2 groups of each serialize and deserialize methods. Then, I have the deserialize for c# (like your API) and a copy with the name changed for VB.NET. This is working, i have another problem, but is in another part.

       
    • Adair Vargas

      Adair Vargas - 2007-09-27

      I Found a bug(???), but i don't know if it is really a bug, and don't know if this is a bug in the API or BerkeleyDB. When i use the Get method for a String,[Custom] pair, Can't get back the first record. I debugged the program and is inserting it, but when i call the get function, all thath i got is not found (even if i call more than 1 looking for the first record.).

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-27

        Well, most often it is not a Berkeley DB error.
        Could you send me a (small) program that shows the bug?

         
      • Karl Waclawek

        Karl Waclawek - 2007-09-28

        OK, it is a bug, but a tricky one. At the end of the buffer I have an array of bits that indicates which fields are null.
        In the last byte, some bits are not used, and my code didn't care about their value, but obviously Berkely Db does.
        I hope this fix works - for file BufferSerialization.cs:

        Add this declaration somewhere before FinishSerialization:

            /// <summary>Bitmask for clearing unused <see cref="SerialStatus"/> values.</summary>
            protected static readonly byte[] clearMasks = { 0x03, 0x0F, 0x3F, 0xFF };

        Then replace FinishSerialization with this code:

            public int FinishSerialization() {
              // save status buffer for re-use
              statusBuf = statusBuffer;

              int bufIndx = startIndx;
              // size should not include prefix size!
              int bufSize = valueIndx - bufIndx - sizeof(uint);
              // write length prefix to start of value buffer
              BEConverter.ToBytes(bufSize, valueBuffer, ref bufIndx);
              int endIndex = valueIndx + nextStatusByte(statusIndx);
              if (valueBuffer.Length < endIndex)
                throw new IndexOutOfRangeException("Buffer size too small.");

              // clear unused bits in status buffer
              if (statusIndx > 0)
                unchecked {
                  int lastStatusIndx = statusIndx - 1;
                  int lastByteIndex = lastStatusIndx >> 2;
                  statusBuffer[lastByteIndex] &= clearMasks[lastStatusIndx & twoBitIndexMask];
                }

              // copy status buffer
              bufIndx = valueIndx;
              bufSize = nextStatusByte(statusIndx);
              System.Buffer.BlockCopy(statusBuffer, 0, valueBuffer, bufIndx, bufSize);

              valueBuffer = null;
              return endIndex;
            }

        Hope it works.

        Karl

         
    • Adair Vargas

      Adair Vargas - 2007-09-27

      Ok, i'll send to you, but actually is a dll the one who works with the DB. I'll send you all the package (Example using my dll, and the new versions of the dlls for VB.NET and C#), the las change inside my version of the API is the DB and Db change, but you can check all the changes I made to keep it working for Both VB and C#

       
    • Adair Vargas

      Adair Vargas - 2007-09-27

      I have one more cuestion, how can i define a custom field type (like in the examples), but inside the library or in another proyect, this because i need tou use a strucuture (like the one in my cuestions) but the user don't want to change their original code (thats why the library for the library)

       
      • Karl Waclawek

        Karl Waclawek - 2007-09-27

        Just define it and register it with the formatter. There is some explanations in the docs.

         
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.