暴露实体框架在WCF服务 [英] Exposing Entity Framework over WCF Service

查看:235
本文介绍了暴露实体框架在WCF服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些帮助在这里!我试图创建使用实体框架,WCF,MVVM和WPF技术,我的第一个应用程序。我是新来的所有的人。所以,我创建了一个模型,使用实体框架我的数据库。然后,我创建我的WCF服务类。我看了近50篇关于EF和WCF服务,我所有关于混乱现在。我知道我不应该直接暴露我的模型。目前我使用这个code为服务合同:

 命名空间Ohmio.DataService
{
    [的ServiceContract]

    公共类OhmioService
    {
        [OperationContract的]
        公开的IEnumerable< vw_Pedidos> ListarPedidos(字符串IDComprobante,布尔bEntregados,INT NUMERO = -1,INT IDCliente = -1)
        {
            使用(VAR上下文=新OhmioTestNet())
            {
                字符串的SqlString =选择值CS由OhmioTestNet.vw_Pedidos AS CS WHERE cs.ID_Comprobante =='+ IDComprobante +'和;
                如果(!NUMERO = -1)的SqlString + =cs.Numero ==+ Numero.ToString()+和;
                如果(!IDCliente = -1)的SqlString + =cs.ID_Cliente ==+ IDCliente.ToString()+和;
                如果(!bEntregados)的SqlString + =cs.Entregado ==虚假和;
                的SqlString = sqlString.Substring(0,sqlString.Length-4);

                的ObjectQuery< vw_Pedidos> Pedidos = context.CreateQuery< vw_Pedidos>(的SqlString);
                VAR的结果= Pedidos.ToList();
                result.ForEach(E => context.Detach(E));
                返回结果;
            }
        }

        [OperationContract的]
        公开的IEnumerable< Clientes> GetClientes()
        {
            使用(VAR上下文=新OhmioTestNet())
            {
                VAR的结果= context.Clientes.Where(F => f.Activo ==真).ToList();
                result.ForEach(E => context.Detach(E));
                返回结果;
            }
        }
    }
}
 

我的问题:

  1. 它的问题是,不认为直接暴露我的数据模型,对吧?所以在这里我要回的类 vw_Pedidos 独立的实体。这是一个不好的做法?

  2. 我已经阅读了很多关于DTO的和POCO的对象,我应该使用上述code呢?

  3. 如果我用DTO或POCO转移了WCF,我必须手动创建一个DTO为每个数据库对象吗?我必须手动创建所有的属性(字段)为每个数据库对象吗?

  4. 如果我添加一个新的领域,以一个数据库对象,并需要证明它的客户,我是否需要更新我的EF模式,手动添加新的字段DTO或POCO对象?这听起来像一个维护的噩梦!

  5. 时使用EntitiesToDTOs一个很好的选择,基于EF对象自动创建DTO的?

  6. 我可以使用DTO,将回更新数据的数据库?

很抱歉的多个问题。请帮我在这里!我在寻找导致我一个易于维护的模式,关注分离code。谢谢!

更新

随着TomTom的建议,我读了很多关于波苏斯,EF和LINQ到实体。从那以后,我重新写我的整个应用程序。我把对5个项目我的code:

1)DataLayer

2)ModelLayer

3)BusinessLyer

4)WCF服务层

5)WPF客户端

有关图层1至5我用用POCO T4模板映射到实体框架POCO类晖,交通运输。的comunicate层4和5比WCF我想用一个自定义的类来隐藏客户端的一些领域(我不希望公开整个POCO类),所以使用LINQ to实体和投影的IEnumerable我重新写过滤功能:

 公开的IEnumerable< PedidosList> Pedidos_Listar(字符串sComprobante,Clientes MyCliente = NULL,日期时间?dDesde = NULL,日期时间?dHasta = NULL,布尔bCumplidos = FALSE)
            {
                使用(VAR上下文=新OhmioEntities())
                {
                    IEnumerable的< PedidosList>查询=
                        从Pedidos在context.Pedidos
                        加入Clientes在context.Clientes上Pedidos.ID_Cliente等于Clientes.ID_Cliente
                        其中,Pedidos.ID_Comprobante == sComprobante
                        选择新PedidosList {ID_Pedido = Pedidos.ID_Pedido,出生日期= Pedidos.Fecha,Aprobado = Pedidos.Aprobado,Bruto = Pedidos.Bruto,Cliente = Clientes.RazonFantasia,
                            FechaEntrega = Pedidos.FechaEntrega,内托= Pedidos.Neto,NUMERO = Pedidos.Numero,Observaciones = Pedidos.Observaciones,Entregado = Pedidos.Entregado,ID_Cliente = Pedidos.ID_Cliente};

                    如果(MyCliente!= NULL)查询= query.Where(I => i.ID_Cliente == MyCliente.ID_Cliente);
                    如果(MyCliente!= NULL)查询= query.Where(I => i.ID_Cliente == MyCliente.ID_Cliente);
                    如果(dDesde = NULL和放大器;!&安培; dHasta!= NULL)查询= query.Where(I => i.Fecha> = dDesde和放大器;&安培; i.Fecha< = dHasta);
                    如果(bCumplidos ==假)查询= query.Where(I => i.Entregado ==假);
                    返回query.ToList();
                }
            }
 

这是做到这一点的最好方法是什么?我可以让过滤器后的投影?谢谢!

解决方案
  

与它的问题是,不认为直接暴露我的数据模型,对吧?所以在这里   我要回班vw_Pedidos的独栋实体。这是一个不好的做法?

是的。

  

我已经阅读了很多关于DTO的和POCO的对象,至极我应该使用上述代替   code?

两者。鉴于一个DTO pretty的多少通常是POCO。也许你试着去理解的话的意思是什么。 POCO是一个普通的旧C#对象(从基类继承不要求),这是完全正常的POCO。

  

如果我用DTO或POCO转移了WCF,我一定要manualy创建一个DTO为每   数据库对象?难道我已经为每个数据库对象manualy创建所有的属性(字段)?

没有。听说过T4的?这可以编写脚本。这就是说,这些通常不是数据库,但API对象 - WCF服务是服务器程序的(公共)前端

  

如果我添加一个新的字段到一个数据库对象,并需要证明它在客户端,我一定要更新我   EF车型,新字段添加manualy到DTO或POCO对象?这听起来   像mantenance nigthmare!

这绝对是其中之一。如果你做的事情没有考虑。严重的是,一旦你已经敲定的基本模式,这是不是发生每隔15分钟。此外,它包括在前端和逻辑的显著的工作无论如何 - 我的意思是,如果属性是没有用的话,嘿,为什么把它?如果不是无用的是大量的工作呢。和模型可以被更新,并不需要再生

哎呀,我通常用不平凡的数据库工作。在这种情况下,变化不是重新生成模型,还包括编写SQL更新脚本版本和测试的更新性能(添加字段到数十亿行的表使用默认值,并生成指数可以需要一些时间)。它仍然没有恶梦,因为这不会发生,每5分钟。 MOST东西是不是添加域,这是程序。

  

我可以使用DTO将数据更新回数据库?

还有什么呢?

  

请帮我在这里!我在寻找导致我一个易于十个分量的模式,   关注分离code

你不会找到一个。这是使权利折衷的问题。你似乎高估了发生在一个项目中,虽然变化量。

您做更多很好的假设,WCF服务是一个信任边界和公共API - 就像一个网站,只是通过电脑的消费。你有公开的对象,不能完全符合数据库内部。最好是单独生成它们,并可能将其更改为更符合需要的是什么了公共API行 - 而不是暴露后端实现细节的API

我不得不说,虽然,你的工作是做了很多更复杂的由您访问数据库的陈旧和绝对禁忌生产方式 - 开始使用适当的SQL生成和对象的映射,或者你将有一个维护的噩梦在那里,你无论怎么做休息。放在一起这样的SQL字符串是一个严重的没有,从来没有。仰望如何通过WCF暴露的OData。这使您可以通过网址查询功能。

I need some help here! I'm trying to create my first application using Entity Framework, WCF, MVVM and WPF technologies. I'm new to all of them. So I create a model for my database using Entity Framework. Then I create my WCF service class. I have read close to 50 articles about EF and WCF services and I'm all about confusion right now. I know that I'm not supposed to expose my model directly. Currently I'm using this code as service contract:

namespace Ohmio.DataService
{
    [ServiceContract]

    public class OhmioService
    {
        [OperationContract]
        public IEnumerable<vw_Pedidos> ListarPedidos(string IDComprobante, bool bEntregados, int Numero = -1, int IDCliente = -1)            
        {
            using (var context = new OhmioTestNet())
            {
                string sqlString="SELECT VALUE cs FROM OhmioTestNet.vw_Pedidos AS cs WHERE cs.ID_Comprobante=='" + IDComprobante + "' AND ";
                if (Numero != -1) sqlString += "cs.Numero=="+ Numero.ToString() +" AND ";
                if (IDCliente != -1) sqlString += "cs.ID_Cliente=="+ IDCliente.ToString()+" AND ";
                if (!bEntregados) sqlString += "cs.Entregado==false AND ";                 
                sqlString =sqlString.Substring(0,sqlString.Length-4);

                ObjectQuery<vw_Pedidos> Pedidos = context.CreateQuery<vw_Pedidos>(sqlString);                
                var result = Pedidos.ToList();
                result.ForEach(e => context.Detach(e));
                return result;
            }
        }

        [OperationContract]
        public IEnumerable<Clientes> GetClientes()
        {
            using (var context = new OhmioTestNet())
            {
                var result = context.Clientes.Where(f => f.Activo == true).ToList();
                result.ForEach(e => context.Detach(e));
                return result;
            }
        }
    }
}

My questions:

  1. The problem with it is that don't suppose to expose my data model directly, right? So here I'm returning detached entity of class vw_Pedidos. Is this a bad practice?

  2. I have read a lot about DTO's and POCO's object, which should I use instead of the above code?

  3. If I use DTO or POCO to transfer over WCF, do I have to manually create a DTO for each database object? Do I have to manually create all the properties (fields) for each DB object?

  4. If I add a new field to a database object and need to show it on client, do I have to update my EF model, add the new field manually to the DTO or POCO object? This sounds like a maintenance nightmare!

  5. Is using EntitiesToDTOs a good option for automatic create DTOs based on EF objects?

  6. Can I use DTO to update data back to database?

Sorry for the multiple questions. Please help me out here! I'm searching for a pattern that lead me to an easy to maintain, concern separated code. Thanks!

UPDATE

Following TomTom suggestions, i read a lot about POCOs, EF and Linq to Entities. After that i re-write my whole app. I divide my code on 5 projects:

1)DataLayer

2)ModelLayer

3)BusinessLyer

4)WCF Service Layer

5)WPF Client

For comunications on layers 1 to 5 I use POCO classes mapped to Entity Framework using POCO T4 Template. To comunicate layer 4 and 5 over WCF I want to use a custom class to hide some field from client (I don't want to expose the whole POCO class) so I re-write filter function using linq to entities and projection to IEnumerable:

public IEnumerable<PedidosList> Pedidos_Listar(string sComprobante, Clientes MyCliente = null, DateTime? dDesde = null, DateTime? dHasta = null, bool bCumplidos = false)
            {           
                using (var context = new OhmioEntities())
                {
                    IEnumerable<PedidosList> query =
                        from Pedidos in context.Pedidos
                        join Clientes in context.Clientes on Pedidos.ID_Cliente equals Clientes.ID_Cliente
                        where Pedidos.ID_Comprobante == sComprobante                    
                        select new PedidosList {ID_Pedido = Pedidos.ID_Pedido, Fecha=Pedidos.Fecha, Aprobado=Pedidos.Aprobado, Bruto=Pedidos.Bruto, Cliente=Clientes.RazonFantasia, 
                            FechaEntrega=Pedidos.FechaEntrega, Neto=Pedidos.Neto, Numero=Pedidos.Numero, Observaciones=Pedidos.Observaciones, Entregado=Pedidos.Entregado, ID_Cliente=Pedidos.ID_Cliente };

                    if (MyCliente != null) query = query.Where(i => i.ID_Cliente == MyCliente.ID_Cliente);
                    if (MyCliente != null) query = query.Where(i => i.ID_Cliente == MyCliente.ID_Cliente);
                    if (dDesde != null && dHasta != null) query = query.Where(i => i.Fecha >= dDesde && i.Fecha <= dHasta);
                    if (bCumplidos == false) query = query.Where(i => i.Entregado == false);                
                    return query.ToList();
                }
            }

Is this the best way to do this? Can i make the projection AFTER the filter? Thanks!

解决方案

The problem with it is that don't suppose to expose my data model directly, right? So here i'm returning dettached entity of class vw_Pedidos. Is this a bad practice?

Yes.

I have read a lot about DTO's and POCO's object, wich should i use instead of the above code?

Both. Given that a DTO pretty much normally is a POCO. Maybe you try to understand what the words MEAN. POCO is a "Plain Old C# Object" (not required to inherit from a base class) and that is totally normal for a POCO.

If I use DTO or POCO to transfer over WCF, do i have to manualy create a DTO for each Database Object? Do I have manualy create all the properties (Fields) for each DB object?

No. Ever heard of T4? That can be scripted. That said, these normally aren't database but API objects - the WCF service is a (public) front end of the server program.

If i add a new field to a DB object and need to show it on client, do i have to update my EF model, add the new field manualy to DTO or POCO object? This sounds like a mantenance nigthmare!

It absolutely is one. If you do things without thinking. Seriously, once you have hammered out the basic model, this is not something that happens every 15 minutes. Also it includes a significant work on the front end and logic anyway - I mean, if the property is useless then hey, why put it in? If it is not useless it is a lot of work anyway. And the models can be updated, not need to regenerate.

Heck, I normally work with non-trivial databases. In this case a change is not "regenerate a model", it also includes "write a sql update script for versioning" and "test the update performance" (adding a field to a multi-billion row table with default value and generating indices can take some time). And it still is no nightmare because this does not happen every 5 minutes. MOST stuff is not "add fields", it is "Program".

Can i use DTO to update data back to database?

What else?

Please help me out here! I'm searching for a pattern that lead me to an easy to mantain, concern separated code

You will not find one. This is a matter of making the right compromise. You DO seem to overestimate the amount of changes that happen in a project though.

You do more well to assume that the WCF service is a trust boundary and public API - much like a website, just for consumption by a computer. The objects you expose there must not absolutely conform to the database internals. It is better to generate them separately and possibly change them to be more in line with what is needed for the public API - than to expose back-end implementation details to an API.

I have to say, though, your work is made a lot more complicated by the archaic and absolutely contra-productive way you access the database - start using a proper sql generator and object mapper, or you'll have a maintenance nightmare right there, regardless how you do the rest. Putting together SQL strings like that is a SERIOUS "no, never". And look up how to expose OData via WCF. That gives you query functionality via URLs.

这篇关于暴露实体框架在WCF服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆