我遇到一個與Windows Phone(SQL Server CE)的LINQ to SQL有關的問題。LINQ to SQL關係不會更新集合
我正在開發一個個人理財應用程序,然後我有Account類和Transaction類。每個交易類都有一個對它所屬賬戶的引用,所以賬戶類具有一系列交易,處於一對多關係。然後我有存儲庫(AccountRepository和TransactionRepository),公開方法插入,刪除,findbykey,並返回每個類的所有實例。 ViewModel引用其存儲庫。好吧,一切正常,但是,當我創建一個事務時,它不會出現在Account.Transactions集合中,直到我停止該軟件並再次運行它。
下面的代碼的一些作品,首先,模型類:
[Table]
public class Transaction : INotifyPropertyChanged, INotifyPropertyChanging
{
// {...}
[Column]
internal int _accountID;
private EntityRef<Account> _account;
[Association(Storage = "_account", ThisKey = "_accountID")]
public Account Account
{
get {return _account.Entity;}
set
{
NotifyPropertyChanging("Account");
_account.Entity = value;
if (value != null)
{
_accountID = value.AccountID;
}
NotifyPropertyChanged("Account");
}
}
// {...}
}
[Table]
public class Account : INotifyPropertyChanged, INotifyPropertyChanging
{
// {...}
private EntitySet<Transaction> _transactions;
[Association(Storage = "_transactions", OtherKey = "_accountID")]
public EntitySet<Transaction> Transactions
{
get { return this._transactions; }
set { this._transactions.Assign(value); }
}
public Account()
{
_transaction = new EntitySet<Transaction>(
new Action<Transaction>(this.attach_transaction),
new Action<Transaction>(this.detach_transaction)
);
}
private void attach_transaction(Transaction transaction)
{
NotifyPropertyChanging("Transactions");
transaction.Account = this;
}
private void detach_transaction(Transaction transaction)
{
NotifyPropertyChanging("Transactions");
transaction.Account = null;
}
// {...}
}
然後,我有一些倉庫實現返回一個ObservableCollection一個GETALL()方法。該庫必須是視圖模型類中創建的上下文類的引用,就像這樣:
public class AccountRepository
{
private MyContext _context;
public AccountRepository(ref MyContext context)
{
_context = context;
}
// {...}
public ObservableCollection<Account> GetAll()
{
return new ObservableCollection(_context.Accounts.Where([some paramethers]).AsEnumerable());
}
// {...}
}
我的視圖模型初始化構造函數中的資料庫,然後暴露了一些很少的邏輯代碼的方法來插入,刪除,等等,每種類型。
public class MyViewModel : INotifyPropertyChanged, INotifyPropertyChanging
{
private MyContext _context;
private AccountRepository accountRepository;
private TransactionRepository transactionRepository;
public ObservableCollection<Account> AllAccounts;
public ObservableCollection<Transaction> AllTransactions;
public MyViewModel(string connectionString)
{
_context = new MyContext("Data Source=’isostore:/mydatabase.sdf’"); if (!db.DatabaseExists()) db.CreateDatabase();
accountRepository = new AccountRepository(ref _context);
transactionRepository = new TransactionRepository(ref _context);
// [Some other code]
LoadCollections();
}
// {...}
public void LoadCollections()
{
AllAccounts = accountRepository.GetAll();
NotifyPropertyChanged("AllAccounts");
AllTransactions = transactionRepository.GetAll();
NotifyPropertyChanged("AllTransactions");
}
public void InsertTransaction(Transaction transaction)
{
AllTransactions.Add(transaction);
transactionRepository.Add(transaction);
LoadCollections(); // Tried this to update the Accounts with newer values, but don't work...
}
// {...}
}
當用戶創建事務,頁面調用視圖模型的InsertTransaction(事務的事務)的方法,即通過交易對象到存儲庫。但Account對象中的Transactions集合不會被更新。然後我試着調用LoadCollections()方法在上下文中強制一個新的查詢,並試圖以某種方式獲得一個新的賬戶對象,但它仍然沒有最近創建的事務。如果我停止我的應用程序並重新啓動它,那麼帳戶是最新的並且具有我在其交易集合中上次運行時創建的所有事務。
如何在運行時更新此事務集合?
更新問題:
我只好向有關通知集合已更改UI的一些反饋。
我認爲這是交易和帳戶之間的關聯問題。一旦我創建了一個事務,它就不會出現在它的account.Transactions集合中,直到我處理我的上下文並再次創建它。
這可能是一些通知錯誤,但我不認爲它是,我做了一些代碼來試圖證明它,我現在不在我的電腦中,但我會嘗試解釋我的測試。
我沒有證明它的代碼是這樣的:
Account c1 = context.Accounts.Where(c => c.AccountID == 1).SingleOrDefault();
Transaction t1 = new Transaction() { Account = c1, {...} };
context.Transactions.InsertOnSubmit(t1);
context.SaveChanges();
c1 = context.Accounts.Where(c => c.AccountID == 1).SingleOrDefault();
// The transaction IS NOT in the c1.Transactions collection right NOW.
context.Dispose();
context = new MyContext({...});
c1 = context.Accounts.Where(c => c.AccountID == 1).SingleOrDefault();
// The transaction IS in the c1.Transactions after the dispose!
Account c2 = context.Where(c => c.AccountID == 2).SingleOrDefault();
t1 = context.Transactions.Where(t => t.TransactionID == x).SingleOrDefault();
t1.Account = c2;
context.SubmitChanges();
c1 = context.Accounts.Where(c => c.AccountID == 1).SingleOrDefault();
// The transaction still in the c1 collection!!!
c2 = context.Accounts.Where(c => c.AccountID == 2).SingleOrDefault();
// It should be in the c2 collection, but isn't yet...
context.Dispose();
context = new MyContext({...});
c1 = context.Accounts.Where(c => c.AccountID == 1).SingleOrDefault();
// The transaction is not in the c1.Transaction anymore!
c2 = context.Accounts.Where(c => c.AccountID == 2).SingleOrDefault();
// The transaction IS in the c2.Transactions now!
獲取交易或與交易和帳戶之間的關聯存在問題嗎?在線'solennsactions = transactionRepository.GetAll();'是集合中的新事務? –
@Kirk Broadhurst對不起,也許我不清楚,英語不是我的第一個語言。問題在於trans和賬戶之間的關聯。如果我添加一個事務,它將不會出現在account.Transactions集合中,直到我處理上下文並再次查詢該帳戶。如果我查詢上下文而不處理它,它將返回該帳戶而不是最近在該關聯中創建的事務。我想,這不是通知UI的問題,因爲如果我調試它,我無法在對象中看到新的事務,我做了一些代碼來證明這一點,我將在家中更新問題。 – Alaor
@Kirk Broadhurst,關於你關於transactionRepository.GetAll()的問題,是的,它在集合中。我可以在調試中觀察到,當我創建事務(例如)時,它沒有事務ID(當然),並且一旦我調用SubmitChanges,內存中的對象就會更新,我可以通過調試來看到它的ID ,我需要的是與關聯集合類似的行爲,當我調用SubmitChanges時,它不會更新集合,即使我再次查詢上下文。只有在處置後,我才能得到最新的。 – Alaor