如何将entity frameworkICollection更改为ObservableCollection?

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

我想另一种选择是让包含所选Customer对象的VM还包含在选择Customer对象时创建的本地ObservableCollection ….我只是担心上下文保存并保持数据同步。

与一组子对象关联的典型代码gen对象:

  public partial class Customer { public Customer() { this.Orders = new HashSet(); } public int Id { get; set; } public System.DateTime Date { get; set; } public virtual ICollection Orders { get; set; } } 

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

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

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

这样就可以替换默认的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())#>>(); } 

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

通常通过DbContext公开的DbSet类具有Local属性,该属性是ObservableCollection 。 有关更多信息,请参阅官方文档

是的,我已经这样做了,它可以成功地用于我的业务应用程序。 我修改了Model.tt文件,使其具有虚拟的ObservableCollection而不是ICollection并用相同的方法替换了HashSet

我还在具有以下实现的实体上实现了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(); } 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 Playtests { get; set; } } }