我遇到一个与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