SQLite, проверьте, если база данных существует и имеет правильные данные, более эффективный способ - PullRequest
0 голосов
/ 09 апреля 2020

Я создаю приложение Xamarin. Android и использую SQLite для некоторых изображений (более 300). Я храню изображения в виде шаблонов в группе из 5 изображений, таких как:

    [Table("Templates")]
    public class Template
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string Name { get; set; }
        public int Category { get; set; }
        [OneToMany]
        public List<TemplateImage> TemplateImages { get; set; }
        public string ImagesHash { get; set; }
    }
    [Table("TemplateImages")]
    public class TemplateImage
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public int Category { get; set; }
        public int Image { get; set; }
        [ForeignKey(typeof(Template))]
        public int TemplateId { get; set; }
    }

. При первом запуске приложения я использую этот код. Чтобы проверить, существует ли база данных, или создайте базу данных:

public static void AddTemplate(int category, List<int> images)
        {
            var tmpl = new Template()
            {
                Category = category,
            };
            if (images != null)
            {
                var img1 = new TemplateImage()
                {
                    Category = category,
                    Image = images[0],
                };
                var img2 = new TemplateImage()
                {
                    Category = category,
                    Image = images[1],
                };
                var img3 = new TemplateImage()
                {
                    Category = category,
                    Image = images[2],
                };
                var img4 = new TemplateImage()
                {
                    Category = category,
                    Image = images[3],
                };
                var img5 = new TemplateImage()
                {
                    Category = category,
                    Image = images[4],
                };
                tmpl.TemplateImages = new List<TemplateImage>() { img1, img2, img3, img4, img5 };
            }
            tmpl.ImagesHash = Guid.NewGuid().ToString();

            DatabaseHelper.Db().InsertAll(tmpl.TemplateImages);
            DatabaseHelper.Db().Insert(tmpl);
            DatabaseHelper.Db().UpdateWithChildren(tmpl);
        }

        public static List<Template> GetAllTemplates()
        {
            return DatabaseHelper.Db().GetAllWithChildren<Template>();
        }

        public static Template GetTemplate(int id)
        {
            var result = DatabaseHelper.Db().GetWithChildren<Template>(id);
            if (result == null)
            {
                result = DatabaseHelper.Db().GetAllWithChildren<Template>().Where(record => record.Category == (int)TemplateCategory.Emojis).OrderBy(record => record.Id).FirstOrDefault();
            }
            return result;
        }

public static void CreateDB()
        {
            DatabaseHelper.Db().RunInTransaction(() =>
            {
                DatabaseHelper.Db().CreateTable<Template>();
                DatabaseHelper.Db().CreateTable<TemplateImage>();
                if (DatabaseHelper.Db().Table<Template>().Count() != 0)
                {
                    return;
                }
                AddTemplate(

                    (int)TemplateCategory.Emojis,
                    new List<int>
                    {
                Resource.Drawable.ic_angry,
                Resource.Drawable.ic_sad,
                Resource.Drawable.ic_neutral,
                Resource.Drawable.ic_happy,
                Resource.Drawable.ic_smiling,
                    }
                );
                AddTemplate(

    (int)TemplateCategory.Emojis,
     new List<int>
                {
                Resource.Drawable.ic_emoji_01_1,
                Resource.Drawable.ic_emoji_01_2,
                Resource.Drawable.ic_emoji_01_3,
                Resource.Drawable.ic_emoji_01_4,
                Resource.Drawable.ic_emoji_01_5,
    }
    );

...//AND many more AddTemplate() functions like those 2.
}

Это работало замечательно, пока я однажды не увидел в очень редкой ситуации, что иногда приложение показывало ... другие изображения из тех, что я выбрал случайным образом. Итак, я понял, что компилятор по некоторым причинам решает изменить ResourceId ImageDrawables и поэтому, несмотря на то, что моя БД существует, это совершенно неправильно,

Итак, я снова начал думать, как правильно делать что-то подобное, не воссоздавая каждый раз базу данных, я нашел идею воссоздать БД каждый раз, когда плохой, но если это единственный правильный путь и Единственный способ, которым я могу быть на 100% уверен в результате, я сохраню его.

Я видел из своих тестов, что обычно меняются первые наборы изображений (Первые шаблоны), и я думал, если это хорошая идея сделать что-то вроде этого:

public static bool ExistingDBItemsFound(int id)
        {
            var returnValue = false;
            var result = GetTemplate(1);
            if (result.TemplateImages.Count == 5)
            {
                if (result.TemplateImages[0].Image == Resource.Drawable.ic_angry
                    && result.TemplateImages[1].Image == Resource.Drawable.ic_sad
                    && result.TemplateImages[1].Image == Resource.Drawable.ic_neutral
                    && result.TemplateImages[1].Image == Resource.Drawable.ic_happy
                    && result.TemplateImages[1].Image == Resource.Drawable.ic_smiling)
                    returnValue = true;
            }
            return returnValue;
        }

Но если я сделаю что-то подобное, как я могу быть уверен, что все остальные идентификаторы ресурсов верны? я только проверяю 5 из 300+.

Можно ли избежать воссоздания каждый раз при создании элементов базы данных приложения? и да как?

Есть ли способ сохранить ресурс в базе данных в другом формате, а не resourceId?

1 Ответ

1 голос
/ 10 апреля 2020

Идентификаторы ресурсов никогда не должны использоваться в качестве уникального идентификатора, так как компилятор может легко изменить их несколько раз, поэтому лучшим подходом было бы полностью избежать их использования.

Одним из решений моей проблемы может быть использование предложенного ответ отсюда: Лучший способ сохранить идентификатор ресурса в базе данных на Android

Получить имя значка

var iconName = Context.Resources.GetResourceEntryName( Resource.Drawable.your_icon );

, а затем получить идентификатор из имени:

var id = Context.Resources.GetIdentifier( iconName, "drawable", Context.PackageName )

Таким образом, даже если идентификатор ресурса изменится, мы получим правильное изображение, если не будем переименовывать наши ресурсы.

Если вы также хотите проверить, имеет ли пользовательская БД правильные значения в качестве вашей apk DB, вы можете сделать что-то вроде того, что предлагает @martin venter, и каким-то образом создать ha sh (например: ha sh имен ресурсов) и сравнить их

...