mbdavid / LiteDB

LiteDB - A .NET NoSQL Document Store in a single data file
http://www.litedb.org
MIT License
8.51k stars 1.24k forks source link

List<T> DbRef throw NullReferanceException #943

Closed Asyvix closed 4 years ago

Asyvix commented 6 years ago

now i'm try this code


        public class DataForm
        {

            [BsonId(true)]
            public ObjectId Id { get; set; }

            public string Name { get; set; } = "Null";
            public string Name2 { get; set; } = "Null";
            public string Name3 { get; set; } = "Null";

            [BsonRef("cImages")]
            public CImage Cimage { get; set; }

        }

        public class CImage
        {
            [BsonId(true)]
            public ObjectId Id { get; set; }
            public string Explanation { get; set; }
            public string Image { get; set; }
        }

        private static LiteDatabase db = new LiteDatabase(@"MyData.db");
        private static LiteCollection<DataForm> lc = db.GetCollection<DataForm>("DF");
        private void button1_Click(object sender, EventArgs e)
        {
            BsonMapper.Global.Entity<DataForm>()
                .DbRef(x => x.Cimage, "cImages");

            DataForm df = new DataForm
            {
                Cimage = new CImage { Explanation = "exp", Image = "exp2"},
            };

            lc.Insert(df); //here. if delete Cimage, not throw exception.
            DataForm df2 = new DataForm
            {
                Cimage = new CImage { Explanation = "exp2", Image = "exp22" },
            };

            lc.Insert(df2);

            foreach (var VARIABLE in lc.FindAll())
            {
                Console.WriteLine(VARIABLE.Cimage.Explanation);
                Console.WriteLine(VARIABLE.Cimage.Image);
                Console.WriteLine(VARIABLE.Cimage.Id);
            }

        }

but it's still make NullReferenceException. Do I have anything wrong?

ty your awesome library.

mbdavid commented 6 years ago

You need insert cImage in another collection to possible reference in dataform collection. See here some example:

https://github.com/mbdavid/LiteDB/blob/master/LiteDB.Tests/Database/DbRef_Include_Tests.cs

Asyvix commented 6 years ago

Thanks for your reply. I've already been using similar code like that, I was wondering if I could implement it a little bit more simply.

tdinucci commented 6 years ago

@Asyvix, I don't know what your requirements are however the code below should work and is very close to what you have - see my comments.

@mbdavid - I don't know what your thoughts are about this and what plans you have. I also think that it would be nice if references were easier to work with, i.e. automatically saved and loaded (but loaded lazily, similar to how EF, NHibernate, etc. do it. Let me know if you'd have any objections to me taking a look at this and submitting a pull request at some point.

public class DataForm
        {
            [BsonId(true)]
            public ObjectId Id { get; set; }

            public string Name { get; set; } = "Null";
            public string Name2 { get; set; } = "Null";
            public string Name3 { get; set; } = "Null";

            // If you don't need Cimage's to live in their own collection then
            // you can get rid of the [BsonRef] attribute.  This will mean the Cimage is embedded 
            // within the DataForm document though, meaning you lose the ability to edit it individually
            //[BsonRef("cImages")]
            public CImage Cimage { get; set; }
        }

        public class CImage
        {
            // The engine doesn't seem to generate Id's for sub-objects, so use ObjectId.NewObjectId() here
            [BsonId(true)]
            public ObjectId Id { get; set; } = ObjectId.NewObjectId(); 

            public string Explanation { get; set; }
            public string Image { get; set; }
        }

        private static LiteDatabase db = new LiteDatabase(@"MyData.db");
        private static LiteCollection<DataForm> lc = db.GetCollection<DataForm>("DF");

        private void button1_Click(object sender, EventArgs e)
        {
            // See my comment above re. [BsonRef] attribute.
            // Also, I think this is just an alternative to using the [BsonRef] attribute - so you wouldn't need this anyway.
            // BsonMapper.Global.Entity<DataForm>().DbRef(x => x.Cimage, "cImages");

            DataForm df = new DataForm
            {
                Cimage = new CImage {Explanation = "exp", Image = "exp2"},
            };

            lc.Insert(df); 
            DataForm df2 = new DataForm
            {
                Cimage = new CImage {Explanation = "exp2", Image = "exp22"},
            };

            lc.Insert(df2);

            foreach (var VARIABLE in lc.FindAll())
            {
                Console.WriteLine(VARIABLE.Cimage.Explanation);
                Console.WriteLine(VARIABLE.Cimage.Image);
                Console.WriteLine(VARIABLE.Cimage.Id);
            }
        }
lbnascimento commented 4 years ago

Hi! With the objective of organizing our issues, we are closing old unsolved issues. Please check the latest version of LiteDB and open a new issue if your problem/question/suggestion still applies. Thanks!