Litedb: [SUGGESTION] I wish to have a feature for handling LiteDb with Isolated Storage

Created on 20 May 2020  Â·  8Comments  Â·  Source: mbdavid/LiteDB

Is your feature request related to a problem? Please describe.
I wish to store some information where I believe IsolatedStorage is the best candidate. The dotnet API does not provide a full path for the IsolatedStorage file where we can pass it to LiteDb to store the database (with reflection its possible, however it is a hack and not a perfect solution I believe).

Describe the solution you'd like
I would like a constructor which accepts IsolatedStorageFile instance and with the other options like Password and other connection string options we can pass.

Describe alternatives you've considered
I tried it with the hack and was not satisfied with the flow of the code, for just getting a field, I had to use reflection, and it is internal which may get renamed anytime.

Additional context
I would be happy if there is another constructor overload with the options mentioned above.

suggestion

All 8 comments

Hi

I think it is already possible with IsolatedStorageFileStream and LiteDatabase constructor overload type ILiteEngine implementation.

I was able to ready LiteDB instance from isolate storage and read / insert documents. Below I’m attaching sample code. It can be enhanced to your needs.

    class Program
    {
        static void Main(string[] args)
        {
            IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForAssembly();

            String[] dirNames = isoFile.GetDirectoryNames("*");
            if (dirNames.Contains("LiteDB") && isoFile.FileExists("LiteDb\\LiteDb.dll")) {
                IsolatedStorageFileStream liteDBStream = isoFile.OpenFile("LiteDb\\LiteDb.dll", System.IO.FileMode.Open);

                var connectionType = LiteDB.ConnectionType.Shared;

                EngineSettings engineSettings = new EngineSettings();
                engineSettings.DataStream = liteDBStream;
                engineSettings.Filename = "LiteDb.dll";
                engineSettings.Password = "1234";
                engineSettings.ReadOnly = false;

                ILiteEngine liteDbEngine = connectionType == LiteDB.ConnectionType.Shared ? 
                    (ILiteEngine)new LiteDB.SharedEngine(engineSettings) : (ILiteEngine)new LiteEngine(engineSettings);

                LiteDB.LiteDatabase liteDatabase = new LiteDB.LiteDatabase(liteDbEngine);

                var testQuery = liteDatabase.GetCollection<TestDto>("query");
                testQuery.Insert(new TestDto() { Name = "Worked" } );

                var result = testQuery.FindAll();

            }
        }
    }

    class TestDto {

        public ObjectId Id { get; set; }
        public string Name {get;set;}
    }

Let me know if this works for you.

Regards
Piotr

@quicksln Your basic idea is good, but your solution lacks some things, like a log stream (if you don't have a FileStream as log stream, there will be data loss in case of a crash). Here's my proposed solution:

```C#
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly();

string path = "myfilepath.db"; //replace this with your datafile path
string logPath = path.Replace(".db", "-log.db");

IsolatedStorageFileStream dataStream = isf.OpenFile(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
IsolatedStorageFileStream logStream = isf.OpenFile(logPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);

EngineSettings settings = new EngineSettings();
settings.DataStream = dataStream;
settings.LogStream = logStream;
settings.ReadOnly = false;
settings.Password = "1234"; //null if no password needed

var connectionType = LiteDB.ConnectionType.Direct; //use this variable to select the connection type
//(Direct is recommended, unless you need multi-process support)

ILiteEngine liteDbEngine = connectionType == LiteDB.ConnectionType.Shared ?
(ILiteEngine)new LiteDB.SharedEngine(settings) : (ILiteEngine)new LiteEngine(settings);

using (LiteDatabase db = new LiteDatabase(liteDbEngine))
{
//do whatever you want here
}
```

@pankaj-nikam

Thank you @quicksln and @lbnascimento :)
The solutions do seem promising. I am wondering if it is good enough to be a feature itself in the package?
Users may find it helpful if it supports isolated storage out of the box.
What do you think?

@lbnascimento good point with adding log file stream, @pankaj-nikam hope you find this useful.

Defiantly it's good candidate for extension method inside individual project :)

Regards
Piotr

Agree with you @quicksln. Its good to make an extension method.

@quicksln It's a possibility, but I'd have to think of a better way to integrate this feature in LiteDB. Maybe adding a log stream parameter in the constructor would be good enough (and it would also be very flexible).

@lbnascimento Agree that could be more helpful and complete solution. What I would like to avoid is to introduce new Ctor. Taking you suggestion I think good candidate for extension is :

        public LiteDatabase(Stream stream, BsonMapper mapper = null)
        {
            var settings = new EngineSettings
            {
                DataStream = stream ?? throw new ArgumentNullException(nameof(stream))
            };
         …
    }

to replace it with

        public LiteDatabase(Stream stream, BsonMapper mapper = null, Stream logStream = null)
        {
            var settings = new EngineSettings
            {
                DataStream = stream ?? throw new ArgumentNullException(nameof(stream)),
                LogStream = logStream
            };

@lbnascimento let me know what you think, I'll create PR to implement this.

@quicksln Yes, somethink like that would be fine. And, if possible, please make some tests for it, just to make sure everything is working as expected (you can use TempStream).

Was this page helpful?
0 / 5 - 0 ratings