用于WCF的CRUD DAL的实体框架的推荐结构

时间:2011-10-09 11:04:28

标签: wcf entity-framework entity-framework-4 crud

我需要为应用程序实现后台层。它必须通过EF4实现数据访问,并通过WCF服务将数据访问公开为CRUD。使用WCF数据服务不是一种选择,因为要求是公开TCP服务端点。

我在Vs 2010中看到EF带有三个EF代码生成器模板:

  1. DbContext生成器,生成从DbContext派生的上下文,将实体类生成为非常简单的POCO,没有额外的代码;

    public partial class MyEntities : DbContext
    {...}
    

    实体类

    ....
    public int EmailAddressLocatorID { get; set; }
    ....
    public virtual Address Address { get; set; }
    ....
    public virtual ICollection<HouseholdGuest> HouseholdGuests { get; set; }
    
  2. EntityObject generator

  3. 自我跟踪实体生成器,生成从ObjectContext派生的上下文,实体为POCO类,实现IObjectWithChangeTrackerINotifyPropertyChanged,以及帮助程序类ObjectChangeTracker

  4. 我在互联网上发现了另一个POCO实体生成器,它生成基于ObjectGenerator的上下文,实体类生成POCO,并带有用于跟踪导航属性的额外代码,如下所示:

        public virtual ICollection<Guest> GuestsAddress
        {
            get
            {
                if (_guestsAddress == null)
                {
                    var newCollection = new FixupCollection<Guest>();
                    newCollection.CollectionChanged += FixupGuestsAddress;
                    _guestsAddress = newCollection;
                }
                return _guestsAddress;
            }
            set
            {
                if (!ReferenceEquals(_guestsAddress, value))
                {
                    var previousValue = _guestsAddress as FixupCollection<Guest>;
                    if (previousValue != null)
                    {
                        previousValue.CollectionChanged -= FixupGuestsAddress;
                    }
                    _guestsAddress = value;
                    var newValue = value as FixupCollection<Guest>;
                    if (newValue != null)
                    {
                        newValue.CollectionChanged += FixupGuestsAddress;
                    }
                }
            }
        }
        private ICollection<Guest> _guestsAddress; 
    

    其中FixupCollection是ObservableCollection的简单增强,实现ClearItemsInsertItem,,如下所示

    public class FixupCollection<T> : ObservableCollection<T>
    {
        protected override void ClearItems()
        {
            new List<T>(this).ForEach(t => Remove(t));
        }
    
        protected override void InsertItem(int index, T item)
        {
            if (!this.Contains(item))
            {
                base.InsertItem(index, item);
            }
        }
    } 
    

    我想请求建议哪些更适合用于通过WCF服务实现CRUD,以及一些实施此目的的最佳实践指南。

    由于

1 个答案:

答案 0 :(得分:2)

  1. 这可能是你提到的最好的方法,但需要付出最大的努力。首先,您必须通过WCF使您的实体可序列化=您必须修改生成器以使用DataContract(IsReference = true)DataMember属性,否则您将在序列化对象图时获得循环引用异常(实体及其主体和从属体之间具有导航属性的关系)。使用对象图后,您还必须进行自己的更改跟踪或数据合并,因为you will not know about changes made on client。如果您不打算传输对象图,但只计划单个对象或相同对象的列表,那么使用此方法就可以了。
  2. EntityObject特定于实体框架并将其暴露给客户是一个坏主意。它默认情况下可由WCF序列化,但它也传输EF特定信息,如EntityKey。服务点应该是隐藏其内部实现,并且暴露基于EntityObject的实体违反了该规则。它也无法解决变更跟踪问题。
  3. STE是专为客户制作的scenario where you want to know about changes in object graphs而设计的,但它们不是灵丹妙药。服务和客户应该只共享描述交换消息的合同。 STE违反了这条规则,因为它们包含逻辑,客户必须知道并使用这种逻辑。 STE基于服务和所有客户端之间的共享实体组合= clients must be .NET application,或者必须在非.NET平台上重新实现相同的逻辑。它们也总是传输整个对象图 - 如果您在图中加载100个实体,则将它们发送回客户端,客户端将更改为图中的单个实体,它将默认将所有100个实体发送回服务。
  4. POCO发生器通常与第一种方法相同。它只使用ObjectContext API而不是DbContext API。 Fixup方法是特定于服务的,客户端不会知道它们。
  5. 最后一种方法是使用自定义非实体类(DTO =数据传输对象)并隐藏DTO与服务中的实体之间的转换。这将允许您创建更复杂和合适的对象集,但它也会使您的应用程序更复杂,并增加开发复杂性。在实施您自己的变更跟踪时,这也是一个选项。