如何将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 logic
和models
应与您的viewmodel
和models
分开。 所以,我认为更好的选择就是你在创建一个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; } } }