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

发布于 2024-12-09 10:10:02 字数 2511 浏览 0 评论 0原文

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

我看到 Vs 2010 中的 EF 附带了 EF 的三个代码生成器模板:

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

    公共分部类 MyEntities : DbContext
    {...}
    

    和实体类

    <前><代码>.... 公共 int EmailAddressLocatorID { 获取;放; } .... 公共虚拟地址Address { get;放; } .... 公共虚拟 ICollectionHouseholdGuests { 得到;放; }
  2. EntityObject 生成器

  3. 自跟踪实体生成器,生成从 ObjectContext 和实体作为 POCO 类实现 IObjectWithChangeTrackerINotifyPropertyChanged, 和辅助类 ObjectChangeTracker

我发现了另一个互联网上有一个 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,以及实现此功能的最佳实践的一些指南。

谢谢

I need to implement a back-office layer for an application. It will have to implement the data access through EF4, and expose the data access as CRUD through WCF services. The using of WCF Data Service is not an option, because the requirements are to expose a TCP service endpoint.

I see EF in Vs 2010 comes with three code-generator templates for EF:

  1. DbContext generator, generates the context derived from DbContext and the entity classes as very simple POCO's with no extra code;

    public partial class MyEntities : DbContext
    {...}
    

    And entity classes

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

  3. Self-tracking entity generator, that generates the context derived from ObjectContext and entities as POCO classes implementing IObjectWithChangeTracker and INotifyPropertyChanged, and helper class ObjectChangeTracker

And I found another one on the internet, POCO entity generator, which generates the context based on ObjectGenerator and the entity classes as POCO with extra code for tracking navigation properties, as below:

    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; 

where FixupCollection is a simple enhancement of ObservableCollection, implementing ClearItems and InsertItem, as below

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

I would like to ask for advise on which of them would be more appropriate for using to implement the CRUD over a WCF service, and some guidelines on best practices implementing this.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

网名女生简单气质 2024-12-16 10:10:02
  1. 这可能是您提到的最好的方法,但需要付出最大的努力。首先,您必须使您的实体可通过 WCF 序列化 = 您必须修改生成器以使用 DataContract(IsReference = true) 和 DataMember 属性,否则您将得到序列化对象图(主体及其关系的实体,其中主体和从属相互具有导航属性)时出现循环引用异常。使用对象图后,您还必须进行自己的更改跟踪或数据合并,因为 您不会知道客户端上所做的更改。如果您不打算传输对象图,而只打算传输单个对象或相同对象的列表,那么您应该可以接受这种方法。
  2. EntityObject 是特定于实体框架的,将其暴露给客户端是一个坏主意。默认情况下,它可由 WCF 序列化,但它也传输 EF 特定信息,例如 EntityKey。服务的重点应该是隐藏其内部实现,而暴露基于 EntityObject 的实体则违反了该规则。它也没有解决变更跟踪问题。
  3. STE 专为您想要了解的场景而设计在客户端上对对象图进行更改,但这并不是灵丹妙药。服务和客户端应该仅共享描述交换消息的合同。 STE 违反了此规则,因为它们包含逻辑,并且客户必须了解并使用此逻辑。 STE 基于在服务和所有客户端之间共享实体组装 = 客户端必须是.NET应用程序或相同的逻辑必须在非.NET平台上重新实现。它们还总是传输整个对象图 - 如果您加载图中的 100 个实体,则将它们发送回客户端,客户端将对图中的单个实体进行更改,默认情况下会将所有 100 个实体发送回服务。
  4. POCO 生成器大体上与第一种方法相同。它只是使用 ObjectContext API 而不是 DbContext API。修复方法是特定于服务的,客户端不会知道它们。

最后一种方法是使用自定义非实体类(DTO = 数据传输对象)并隐藏服务中 DTO 和实体之间的转换。这将允许您创建更复杂和合适的对象集,但它也会使您的应用程序更加复杂并增加开发复杂性。如果您要实现自己的更改跟踪,这也是一个选项。

  1. This is probably the best approach from those you mentioned but it will require the biggest effort. First of all you will have to make your entities serializable by WCF = you will have to modify generator to use DataContract(IsReference = true) and DataMember attributes because otherwise you will get cyclic reference exception when serializing object graph (entity with its relations where both principal and dependent have navigation property to each other). Once using object graphs you will also have to make your own change tracking or data merging because you will not know about changes made on client. If you don't plan to transfer object graphs but only single objects or list of the same objects you should be OK with this approach.
  2. EntityObject is specific to Entity Framework and exposing it to clients is a bad idea. It is by default serializable by WCF but it also transfers EF specific information like EntityKey. The point of service should be to hide its internal implementation and exposing EntityObject based entities is violation of that rule. It also doesn't solve change tracking problem.
  3. STEs are designed for the scenario where you want to know about changes in object graphs made on clients but they are not a silver bullet. Services and clients should share only contract describing exchanged messages. STEs violate this rule because they contain logic and client must know and use this logic. STEs are based on sharing entity assembly between service and all clients = clients must be .NET application or the same logic must be reimplemented on non-.NET platform. They also always transfer whole object graph - if you load 100 entities in graph send them back to client and client will make change to single entity in graph it will by default send all 100 entities back to the service.
  4. POCO generator is generally the same as the first approach. It just uses ObjectContext API instead of DbContext API. Fixup methods are service specific and client will not know about them.

The last approach is using custom non entity classes (DTOs = Data transfer objects) and hide conversion between DTOs and entities in your service. That will allow you to create more complex and suitable set of objects but it will also make your application more complex and increase development complexity. This will be also option in case of implementing your own change tracking.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文