如何将实体框架ICollection更改为ObservableCollection?

时间:2013-06-12 18:52:05

标签: c# entity-framework mvvm

所以我在使用Entity Framework设计器创建一个EDMX作为MVVM项目中的模型时,已经走得很远了。 我刚刚遇到一个问题,我很确定代码生成的ICollection<>(例如见下文)确实需要ObservableCollection<>来将该集合绑定到{{1}在一个视图中成功。 我认为我对修改EF代码生成以制作DataGrid而不是ObservableCollections的可能性有所了解。有没有人成功尝试过?

我认为另一个选择是让包含所选Customer对象的VM还包含在选择Customer对象时创建的本地ICollections ....我只是担心上下文保存并保留数据同步。

与子对象集合关联的典型代码gen对象:

ObservableCollection<Order>

4 个答案:

答案 0 :(得分:7)

这就是我所做的以及首先使用EF数据库对我有用的东西。

这就是你需要生成的东西:

public partial class Parent
{
    public Parent()
    {
        this.Children= new ObservableCollection<Child>();
    }

这样就可以替换默认的costructor。 而ObservableCollection是ICollection,因此您无需更改任何其他内容。

要在每次更新数据库模型时都显示此内容,您必须使用以下部分更改.tt文件:

public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
    return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
        ? string.Format(
            CultureInfo.InvariantCulture,
            "{0}using System;{1}" +
            "{2}",
            inHeader ? Environment.NewLine : "",
            includeCollections ? (Environment.NewLine + "using System.Collections.ObjectModel;" 
                + Environment.NewLine + "using System.Collections.Generic;") : "",
            inHeader ? "" : Environment.NewLine)
        : "";
}

和此:

    foreach (var navigationProperty in collectionNavigationProperties)
    {

    this.<#=code.Escape(navigationProperty)#> = new ObservableCollection<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
    }

答案 1 :(得分:4)

您的data logicmodels应与viewmodelmodels分开。所以,我认为更好的选择就是你在创建ObservableCollection时所说的。保存时,您始终可以同步到上下文(我忘记了要同步的确切语法)。

答案 2 :(得分:4)

通常通过DbSet公开的DbContext类的Local属性为ObservableCollection<T>。有关详细信息,请参阅the official documentation

答案 3 :(得分:2)

是的,我已经完成了这项工作,它可以成功地用于我的业务应用程序。我将Model.tt文件修改为虚拟ObservableCollection<T>而不是ICollection<T>,并将HashSet<T>替换为INotifyPropertyChanged

我还在具有以下实现的实体上实现了public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } }

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;

我需要包含三个额外的使用语句:

public string Property(EdmProperty edmProperty)
{
    var fourSpaces = "    ";
    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1} _{2};{3}{4}{0} {1} {2}{3}{4}{{{3}{4}{4}{5}get {{ return _{2}; }} {3}{4}{4}{6}set{3}{4}{4}{{{3}{4}{4}{4}if (value == _{2}) return;{3}{4}{4}{4}_{2} = value;{3}{4}{4}{4}NotifyPropertyChanged();{3}{4}{4}}}{3}{4}}}{3}",
        Accessibility.ForProperty(edmProperty),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        Environment.NewLine,
        fourSpaces,
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

这是我在CodeStringGenerator中更改的函数,用于实现我的getter和setter :(抱歉,我还没有让它更具可读性)

namespace Eagl.Eagle.Data
{
    using System;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;

    public partial class Game : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public Game()
        {
            this.Playtests = new ObservableCollection<Playtest>();
        }

        public int _Id;
        public int Id
        {
            get { return _Id; } 
            set
            {
                if (value == _Id) return;
                _Id = value;
                NotifyPropertyChanged();
            }
        }

        public string _Name;
        public string Name
        {
            get { return _Name; } 
            set
            {
                if (value == _Name) return;
                _Name = value;
                NotifyPropertyChanged();
            }
        }


        public virtual ObservableCollection<Playtest> Playtests { get; set; }
    }
}

这是一个完整生成的实体文件样本供参考:

{{1}}