我怎样才能改变一个实体框架ICollection的是一个ObservableCollection?我

2019-05-12 06:00发布

所以我很远了使用实体框架设计,使一个EDMX它用作一个MVVM项目模型的兔子洞。 我刚刚碰到,我敢肯定的是,问题ICollection<>生成的代码(见下文的例子)真正需要的是一个ObservableCollection<>该集合绑定到DataGrid视图中获得成功。 我我得到关于修改EF代码生成,使的可能性,一些命中ObservableCollections而非ICollections 。 任何一个曾经尝试过成功?

我想另一个办法是有一个包含选定的客户对象也包含本地虚拟机ObservableCollection<Order>所选择的客户对象时被创建....我只是担心的背景下保存并保持数据同步。

典型的代码生成的对象与关联到子对象的集合:

    public partial class Customer
{
    public Customer()
    {
        this.Orders = new HashSet<Order>();
    }

    public int Id { get; set; }
    public System.DateTime Date { get; set; }

    public virtual ICollection<Order> Orders { get; set; }
}

Answer 1:

这就是我做什么首先对我的作品与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())#>>();
    }


Answer 2:

您的data logicmodels应该是从你的单独viewmodelmodels 。 所以,我认为更好的选择是你在建立一个谈论ObservableCollection 。 您可以随时同步到上下文(我忘了确切的语法同步)当您保存。



Answer 3:

DbSet经由您通常暴露类DbContext具有Local属性其是ObservableCollection<T> 请参见官方文档以了解更多信息



Answer 4:

是的,我已经做到了这一点,它成功的作品对我的业务应用。 我修改了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语句:

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

这是我在CodeStringGenerator改变来实现我的getter和setter函数(对不起,我还没有恢复过来,以使这个更具可读性)

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)));
}

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

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; }
    }
}


文章来源: How can I change an Entity Framework ICollection to be an ObservableCollection?