locked
Работа с локальной базой данных RRS feed

  • Вопрос

  • Есть 2 класса для работы с БД
    namespace Database
    {
        [Table]
        public class Currency : INotifyPropertyChanging, INotifyPropertyChanged
        {
    
            private int id;
            private string name;
            private string isoCode;
            private string suffix;
            private int digets = 2;
            private bool main = false;
            private EntitySet<CurrencyRate> rates;
    
            [Column(CanBeNull = false, IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
            public int ID
            {
                get
                {
                    return id;
                }
                set
                {
                    if (id != value)
                    {
                        NotifyPropertyChanging("ID");
                        id = value;
                        NotifyPropertyChanged("ID");
                    }
                }
            }
    
            [Column(CanBeNull = false)]
            public string Name
            {
                get
                {
                    return name;
                }
                set
                {
                    if (name != value)
                    {
                        NotifyPropertyChanging("Name");
                        name = value;
                        NotifyPropertyChanged("Name");
                    }
                }
            }
    
            [Column(CanBeNull = false)]
            public string ISOCode
            {
                get
                {
                    return isoCode;
                }
                set
                {
                    if (isoCode != value)
                    {
                        NotifyPropertyChanging("ISOCode");
                        isoCode = value;
                        NotifyPropertyChanged("ISOCode");
                    }
                }
            }
    
            [Column(CanBeNull = true)]
            public string Suffix
            {
                get
                {
                    return suffix;
                }
                set
                {
                    if (suffix != value)
                    {
                        NotifyPropertyChanging("Suffix");
                        suffix = value;
                        NotifyPropertyChanged("Suffix");
                    }
                }
            }
    
            [Column(CanBeNull = false)]
            public int Digets
            {
                get
                {
                    return digets;
                }
                set
                {
                    if (digets != value)
                    {
                        NotifyPropertyChanging("Digets");
                        digets = value;
                        NotifyPropertyChanged("Digets");
                    }
                }
            }
    
            [Association(Storage = "rates", OtherKey = "currencyId", ThisKey = "ID")]
            public EntitySet<CurrencyRate> Rates
            {
                get
                {
                    return rates;
                }
                set
                {
                    rates.Assign(value);
                }
            }
    
            [Column]
            public bool IsMain
            {
                get
                {
                    return main;
                }
                set
                {
                    if (main != value)
                    {
                        NotifyPropertyChanging("IsMain");
                        main = value;
                        NotifyPropertyChanged("IsMain");
                    }
                }
            }
    
            public Currency()
            {
                rates = new EntitySet<CurrencyRate>(
                    new Action<CurrencyRate>(attach_Rate),
                    new Action<CurrencyRate>(detach_Rate)
                    );
            }
    
            private void attach_Rate(CurrencyRate rate)
            {
                NotifyPropertyChanging("Rate");
                rate.Currency = this;
            }
    
            private void detach_Rate(CurrencyRate rate)
            {
                NotifyPropertyChanging("Rate");
                rate.Currency = null;
            }
    
            #region INotifyPropertyChanging
    
            public event PropertyChangingEventHandler PropertyChanging;
    
            protected virtual void NotifyPropertyChanging(string PropName)
            {
                if (PropertyChanging != null)
                    PropertyChanging(this, new PropertyChangingEventArgs(PropName));
            }
    
            #endregion
    
            #region INotifyPropertyChanged
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void NotifyPropertyChanged(string PropName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(PropName));
            }
    
            #endregion
        }
    }
    
    

    namespace Database
    {
        [Table]
        public class CurrencyRate: INotifyPropertyChanging, INotifyPropertyChanged
        {
    
            private int id;
            [Column(CanBeNull = false)]
            internal int currencyId;
            private EntityRef<Currency> currency;
            private DateTime date;
            private double rate;
    
            [Column(IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, AutoSync = AutoSync.OnInsert)]
            public int ID
            {
                get
                {
                    return id;
                }
                set
                {
                    if (id != value)
                    {
                        NotifyPropertyChanging("ID");
                        id = value;
                        NotifyPropertyChanged("ID");
                    }
                }
            }
    
            [Association(Storage = "currency", ThisKey = "currencyId", OtherKey = "ID", IsForeignKey = true)]
            public Currency Currency
            {
                get
                {
                    return currency.Entity;
                }
                set
                {
                    NotifyPropertyChanging("Currency");
                    currency.Entity = value;
                    if (value != null)
                    {
                        currencyId = value.ID;
                    }
                    NotifyPropertyChanged("Currency");
                }
            }
    
            [Column(CanBeNull = false)]
            public DateTime Date
            {
                get
                {
                    return date;
                }
                set
                {
                    if (date != value)
                    {
                        NotifyPropertyChanging("Date");
                        date = value;
                        NotifyPropertyChanged("Date");
                    }
                }
            }
    
            [Column(CanBeNull = false)]
            public double Rate
            {
                get
                {
                    return rate;
                }
                set
                {
                    if (rate != value)
                    {
                        NotifyPropertyChanging("Rate");
                        rate = value;
                        NotifyPropertyChanged("Rate");
                    }
                }
            }
    
            #region INotifyPropertyChanging
    
            public event PropertyChangingEventHandler PropertyChanging;
    
            private void NotifyPropertyChanging(string PropertyName)
            {
                if (PropertyChanging != null)
                    PropertyChanging(this, new PropertyChangingEventArgs(PropertyName));
            }
    
            #endregion
    
            #region INotifyPropertyChanged
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void NotifyPropertyChanged(string PropertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
    
            #endregion
        }
    }
    
    

    Есть контекст базы
    namespace Database
    {
        public class MoneyWalletDataContext : DataContext
        {
            public MoneyWalletDataContext(string connectionString)
                : base(connectionString)
            { }
    
            public Table<Currency> Currencies;
            public Table<CurrencyRate> CurrencyRates;
    }
    

    При запуске приложения, если базы нет, то я ее создаю. Кроме того, после создания базы я добавляю в нее начальные данные и фиксирую их через SubmitChanges() (элементы добавляются и в таблицу Currency, и в CurrencyRate)
    Проблема в том, что при первом запуске приложения, когда создается база и заполняется данныеми, у элементов Currency список Rates пустой. Если же закрыть приложение и запустить его заново, то этот список заполняется корректно.
    Код заполнения данными:
            public void FillTables()
            {
                //Determining current culture to set default currency
                CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
                //Adding 3 main currencies
                switch (cultureInfo.Name)
                {
                    case "en-US": 
                        Currencies.InsertOnSubmit(new Database.Currency { Name = "US Dollar", ISOCode = "USD", Suffix = "$", IsMain = true });
    
                        CurrencyRates.InsertOnSubmit(new Database.CurrencyRate { currencyId = 1, Date = DateTime.Now, Rate = 1 });
                        break;
                    case "ru-RU":
                        Currencies.InsertOnSubmit(new Database.Currency { Name = "Российский рубль", ISOCode = "RUR", Suffix = "р.", IsMain = true });
                        Currencies.InsertOnSubmit(new Database.Currency { Name = "US Dollar", ISOCode = "USD", Suffix = "$" });
                        Currencies.InsertOnSubmit(new Database.Currency { Name = "Euro", ISOCode = "EUR", Suffix = "€" });
    
                        CurrencyRates.InsertOnSubmit(new Database.CurrencyRate { currencyId = 1, Date = DateTime.Now, Rate = 1 });
                        CurrencyRates.InsertOnSubmit(new Database.CurrencyRate { currencyId = 2, Date = DateTime.Now, Rate = 32.11 });
                        CurrencyRates.InsertOnSubmit(new Database.CurrencyRate { currencyId = 3, Date = DateTime.Now, Rate = 43.4191 });
                        break;
                    default:
                        Currencies.InsertOnSubmit(new Database.Currency { Name = "Euro", ISOCode = "EUR", Suffix = "€", IsMain = true });
    
                        CurrencyRates.InsertOnSubmit(new Database.CurrencyRate { currencyId = 1, Date = DateTime.Now, Rate = 1 });
                        break;
                }
    
                SubmitChanges();
            }
    
    

    Не могу понять, в чем проблема.
    Получение данных происходит при переходе на страницу       
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                //Getting currencies
                var cur = from Database.Currency rec in dbContext.Currencies
                          orderby rec.ID
                          select rec;
                Currencies = new ObservableCollection<Database.Currency>(cur);
    
                base.OnNavigatedTo(e);
            }
    
    

    4 октября 2011 г. 5:29

Ответы

  • К сожалению нет, одной таблице не обойтись, потому как нужно хранить историю курса валюты.

    Именно данную проблему обошел следующим образом:

     using (Database.MyDataContext db = new Database.MyDataContext(Database.MyDataContext.DBConnectionString))
                {
                    if (!db.DatabaseExists())
                    {
                        //Creating database
                        db.CreateDatabase();
                        //Filling database
                        db.FillDatabase();
                    }
                }
                DBContext = new Database.MyDataContext(Database.MyDataContext.DBConnectionString);
    
    

    т.е. база создается и заполянется во временной переменной, после чего основная переменная, содержащая контекст БД создается после.

    • Помечено в качестве ответа Abolmasov Dmitry 11 октября 2011 г. 9:40
    11 октября 2011 г. 4:51

Все ответы

  • Уважаемый пользователь!

     

    В вашей теме отсутствует активность в течение последних 5 дней. При отсутствии каких-либо действий в течение 2 последующих дней, тема будет переведена в разряд обсуждений. Вы можете возобновить дискуссию, просто оставив сообщение в данной теме.
    9 октября 2011 г. 10:26
  • Думаю дело может быть в том, что вы тут реализуете отношение один ко многим, хотя по сути это один к одному. Если взглянуть на содержимое таблицы CurrencyRates при первом запуске, то там Entities с Currency присутствуют, т.е. всё нормально (Rates в коде): 

     

                var cur = from MSDN_ПРоблемы_с_локальной_базой.Currency rec in dbContext.Currencies
                          orderby rec.ID
                          select rec;
                var rat = from CurrencyRate rec in dbContext.CurrencyRates
                          orderby rec.ID
                          select rec;
                Currencies = new ObservableCollection<MSDN_ПРоблемы_с_локальной_базой.Currency>(cur);
                Rates = new ObservableCollection<CurrencyRate>(rat);
    

     


    Отношение один к одному реализуется с помощью двух EntitySet (один должен быть в Currency и содержать CurrencyRate, другой в CurrencyRates и содержать Currency) на сколько я понимаю. Что-то на эту тему есть тут:

    http://msdn.microsoft.com/ru-ru/library/Bb386950(v=VS.90).aspx 

    А тут другой рецепт через один EntityRef, мне более понятный:

    http://www.codeproject.com/KB/linq/OneManyandOneOneLINQ.aspx

    Или может быть в данном случае вообще не нужно две таблицы. А можно обойтись одной?
    • Изменено Leonid Vasilyev 10 октября 2011 г. 19:31
    • Предложено в качестве ответа Leonid Vasilyev 10 октября 2011 г. 22:47
    10 октября 2011 г. 18:43
  • К сожалению нет, одной таблице не обойтись, потому как нужно хранить историю курса валюты.

    Именно данную проблему обошел следующим образом:

     using (Database.MyDataContext db = new Database.MyDataContext(Database.MyDataContext.DBConnectionString))
                {
                    if (!db.DatabaseExists())
                    {
                        //Creating database
                        db.CreateDatabase();
                        //Filling database
                        db.FillDatabase();
                    }
                }
                DBContext = new Database.MyDataContext(Database.MyDataContext.DBConnectionString);
    
    

    т.е. база создается и заполянется во временной переменной, после чего основная переменная, содержащая контекст БД создается после.

    • Помечено в качестве ответа Abolmasov Dmitry 11 октября 2011 г. 9:40
    11 октября 2011 г. 4:51
  • Да, действительно. Наткнулся на обсуждения типа почему Refresh DataContext'а не работет (интересно, что в вашем случае я его тоже попробовал, не помогло) и там как раз предлагали создавать новый объект этого контекста.

    Кстати вы видимо за основу брали этот пример:

    http://msdn.microsoft.com/en-us/library/hh286405(v=VS.92).aspx#BKMK_CompletingTheApplication

    И там эту проблему видимо решает создание ViewModel по тому же ConnectionString'у.

    Тоже интересно из каких соображений вы используется какбы обрезанный mvvm? Без ViewModel.

    12 октября 2011 г. 15:28