【问题标题】:Is passing a L2S DataContext into a ViewModel constructor clean MVVM?是否将 L2S DataContext 传递给 ViewModel 构造函数干净的 MVVM?
【发布时间】:2009-12-26 19:50:04
【问题描述】:

在我的主 Window1.xaml.cs 中,我通过使用 LINQ-to-SQL 模型对象进行实例化,像这样构建 ObservableCollection of ViewModels

using (var db = Datasource.GetContext())
{
    var customers = from c in db.Customers
                    select c;

    foreach (var customer in customers)
    {
        CustomerCollection.Add(new CustomerModelView(customer));
    }
}  

在每个 ViewModel 的 constructor 中,我在内部保存 LINQ-to-SQL 对象并将所有属性从 Model 映射到 ViewModel:

#region ViewModelProperty: Customer
private Customer _customer;
public Customer Customer
{
    get
    {
        return _customer;
    }

    set
    {
        _customer = value;
        OnPropertyChanged("Customer");
    }
}
#endregion

#region ViewModelProperty: FirstName
private string _firstName;
public string FirstName
{
    get
    {
        return _firstName;
    }

    set
    {
        _firstName = value;
        OnPropertyChanged("FirstName");
    }
}
#endregion

...

public CustomerViewModel(Customer customer)
{
    Customer customer;
    FirstName = customer.FirstName;
    ...
}

问题是在我的 ViewModel 中处理事件时,例如用户更改任何字段并单击Save 按钮后,我必须重新实例化 LINQ-to-SQL 对象以保存更改,这会导致进出数据库的流量增加当我实际上已经在内部保存了对象时:

using (var db = Datasource.GetContext())
{
    var customer = (from c in db.Customers
                 where c.Id == Id
                 select c).SingleOrDefault();

    customer.FirstName = FirstName;
    db.SubmitChanges();
} 

直接的解决方案是在实例化 ViewModel 时也将 LINQ-to-SQL datacontext object 传递给 ViewModel,如下所示:

public CustomerViewModel(Customer customer, DataClasses1DataContext db)
{
    Customer = customer;
    Db = db;

    FirstName = customer.FirstName;
    ...
}

然后在处理诸如Save 按钮之类的事件时,我可以在internal Db 变量上调用SubmitChanges() 而无需重新实例化它并再次从数据库中获取数据。

所以看来我必须(1)将数据层上下文对象传递到 ViewModel 中,这似乎不是解决此问题的 clean MVVM 方法,或者(2)我必须每次我想保存已经在 ViewModel 内部保存的模型对象时,重新获取我的 LINQ-to-SQL 对象。

解决这个困境的最简洁的 MVVM 方法是什么?

【问题讨论】:

    标签: c# wpf linq-to-sql mvvm


    【解决方案1】:

    这意味着您的 ViewModel 了解数据层。我认为最好使用对象初始化上下文。这也允许您这样做:

    using (var db = Datasource.GetContext())
    {
        var customers = from c in db.Customers
                        select new CustomerModelView
                        {
                            Name = c.Name;
                            Address = c.Address;
                        };
    
        CustomerCollection.AddRange(customers);
    }
    

    更新数据库时,您应该能够创建一个新对象,然后使用db.AttachObject 使上下文知道它。这样您就不必为了更改它而从数据库中重新获取它。

    【讨论】:

    • +1 用于附加。这是正确的做法。让 ViewModel 将模型对象存储在 Model 属性中,并在往返时使用 attach。
    • @Anderson:我不认为将模型对象附加到视图模型实际上是一个好主意。当往返真正的页面帖子时,它不会被序列化,并且它还引入了两者的紧密耦合。视图模型应该只包含数据,仅此而已..
    • 这是一个 View*Model* 这就是重点。这两个词在这里都很重要。我看到很多人引入了另一种构造,例如控制器,它充当视图模型和模型之间的润滑层,但我不认为这是必须具备的。
    • 问题是当视图模型对象在页面上被渲染,并且执行一个帖子时,模型对象丢失了。所以 something 需要重新创建模型对象。您不能将模型对象粘贴在视图模型上,并期望它在后循环中存活
    • 是的...但那是 ASP.NET,而不是 WPF。使用 WPF 标签发布的 OP。
    猜你喜欢
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多