gpt4 book ai didi

entity-framework - 如何使用 WCF 数据服务/OData 从 sproc 使用复杂对象?

转载 作者:行者123 更新时间:2023-12-04 21:22:20 25 4
gpt4 key购买 nike

使用 WCF 数据服务(和最新的 Entity Framework ),我想从存储过程返回数据。返回的 sproc 字段与我的数据库中的任何实体都不匹配 1:1,因此我在 edmx 模型中为其创建了一个新的复杂类型(而不是附加现有实体):

  • 右键单击*.edmx 模型/添加/函数导入
  • 选择 sproc(返回三个字段)- GetData
  • 点击获取栏目信息
  • 添加函数导入名称:GetData
  • 单击创建新的复杂类型 - GetData_Result

  • 在服务中,我定义:
        [WebGet]
    public List<GetData_Result> GetDataSproc()
    {
    PrimaryDBContext context = new PrimaryDBContext();
    return context.GetData().ToList();
    }

    我创建了一个快速控制台应用程序进行测试,并添加了对 System.Data.Services 的引用。和 System.Data.Services.Client - 运行后的这个 Install-Package EntityFramework -Pre ,但库上的版本是 4.0 而不是 5.x。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.Services.Client;
    using ConsoleApplication1.PrimaryDBService;

    namespace ConsoleApplication1
    {
    class Program
    {
    static void Main(string[] args)
    {
    DataServiceContext context = new DataServiceContext(new Uri("http://localhost:50100/PrimaryDataService1.svc/"));
    IEnumerable<GetData_Result> result = context.Execute<GetData_Result>(new Uri("http://localhost:50100/PrimaryDataService1.svc/GetDataSproc"));
    foreach (GetData_Result w in result)
    {
    Console.WriteLine(w.ID + "\t" + w.WHO_TYPE_NAME + "\t" + w.CREATED_DATE);
    }

    Console.Read();
    }
    }
    }

    我没有使用 UriKind.Relative或其他任何使这复杂化的事情。

    当我在浏览器中导航到 URL 时,我会看到数据,但是当我在控制台应用程序中使用它时,我什么也得不到。

    将跟踪添加到混合中:
      <system.diagnostics>
    <sources>
    <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
    <listeners>
    <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\temp\WebWCFDataService.svclog" />
    </listeners>
    </source>
    </sources>
    </system.diagnostics>

    ...并使用 Microsoft 服务跟踪查看器打开,我看到两个相同的警告:

    Configuration evaluation context not found.


    <E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
    <EventID>524312</EventID>
    <Type>3</Type>
    <SubType Name="Warning">0</SubType>
    <Level>4</Level>
    <TimeCreated SystemTime="2012-04-03T14:50:11.8355955Z" />
    <Source Name="System.ServiceModel" />
    <Correlation ActivityID="{66f1a241-2613-43dd-be0c-341149e37d30}" />
    <Execution ProcessName="WebDev.WebServer40" ProcessID="5176" ThreadID="10" />
    <Channel />
    <Computer>MyComputer</Computer>
    </System>
    <ApplicationData>
    <TraceData>
    <DataItem>
    <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning">
    <TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.EvaluationContextNotFound.aspx</TraceIdentifier>
    <Description>Configuration evaluation context not found.</Description>
    <AppDomain>fd28c9cc-1-129779382115645955</AppDomain>
    </TraceRecord>
    </DataItem>
    </TraceData>
    </ApplicationData>
    </E2ETraceEvent>

    那么为什么我可以从浏览器看到数据,但在我的应用程序中使用时却看不到?

    - 更新 -

    我下载了 Microsoft WCF Data Services October 2011 CTP其中曝光 DataServiceProtocolVersion.V3 ,创建了一个新的主机和客户端并引用了 Microsoft.Data.Services.Client (v4.99.2.0)。现在尝试在 foreach 中迭代时在客户端上出现以下错误环形:

    There is a type mismatch between the client and the service. Type 'ConsoleApplication1.WcfDataServiceOctCTP1.GetDataSproc_Result' is an entity type, but the type in the response payload does not represent an entity type. Please ensure that types defined on the client match the data model of the service, or update the service reference on the client.



    我通过引用实际实体尝试了同样的事情 - 工作正常,所以同样的问题。

    最佳答案

    回顾:我想创建一个高性能的 WCF 服务 DAL(数据访问层),它返回强类型存储过程。我最初使用“WCF 数据服务”项目来完成此任务。似乎它有其局限性,并且经过审查 performance metrics不同的 ORM,我最终使用了 Dapper用于基本 WCF 服务内的数据访问。

    我首先创建了 *.edmx 模型并为我的 sproc 创建了 POCO。

    接下来,我创建了一个基础 BaseRepository 和 MiscDataRepository:

    namespace WcfDataService.Repositories
    {
    public abstract class BaseRepository
    {
    protected static void SetIdentity<T>(IDbConnection connection, Action<T> setId)
    {
    dynamic identity = connection.Query("SELECT @@IDENTITY AS Id").Single();
    T newId = (T)identity.Id;
    setId(newId);
    }

    protected static IDbConnection OpenConnection()
    {
    IDbConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["PrimaryDBConnectionString"].ConnectionString);
    connection.Open();
    return connection;
    }
    }
    }

    namespace WcfDataService.Repositories
    {
    public class MiscDataRepository : BaseRepository
    {
    public IEnumerable<GetData_Result> SelectAllData()
    {
    using (IDbConnection connection = OpenConnection())
    {
    var theData = connection.Query<GetData_Result>("sprocs_GetData",
    commandType: CommandType.StoredProcedure);

    return theData;
    }
    }
    }
    }

    服务类:
    namespace WcfDataService
    {
    public class Service1 : IService1
    {
    private MiscDataRepository miscDataRepository;

    public Service1()
    : this(new MiscDataRepository())
    {
    }

    public Service1(MiscDataRepository miscDataRepository)
    {
    this.miscDataRepository = miscDataRepository;
    }

    public IEnumerable<GetData_Result> GetData()
    {
    return miscDataRepository.SelectAllData();
    }
    }
    }

    ...然后创建一个简单的控制台应用程序来显示数据:
    namespace ConsoleApplication1
    {
    class Program
    {
    static void Main(string[] args)
    {
    Service1Client client = new Service1Client();
    IEnumerable<GetData_Result> result = client.GetData();
    foreach (GetData_Result d in result)
    {
    Console.WriteLine(d.ID + "\t" + d.WHO_TYPE_NAME + "\t" + d.CREATED_DATE);
    }
    Console.Read();
    }
    }
    }

    我还使用 PetaPOCO 完成了此操作,它比 Dapper 花费更少的时间来设置 - 几行代码:
    namespace PetaPocoWcfDataService
    {
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
    public IEnumerable<GetData_Result> GetData()
    {
    var databaseContext = new PetaPoco.Database("PrimaryDBContext"); // using PetaPOCO for data access
    databaseContext.EnableAutoSelect = false; // use the sproc to create the select statement

    return databaseContext.Query<GetData_Result>("exec sproc_GetData");
    }
    }
    }

    我喜欢设置 PetaPOCO 是多么快速和简单,但是将存储库模式与 Dapper 一起使用会更好地扩展企业项目。

    直接从 EDMX 创建复杂对象也非常简单 - 对于任何存储过程,然后使用它们。

    例如,我创建了名为 ProfileDetailsByID_Result 的复杂类型返回类型。基于 sq_mobile_profile_get_by_id过程。
    public ProfileDetailsByID_Result GetAllProfileDetailsByID(int profileID)
    {
    using (IDbConnection connection = OpenConnection("DatabaseConnectionString"))
    {
    try
    {
    var profile = connection.Query<ProfileDetailsByID_Result>("sq_mobile_profile_get_by_id",
    new { profileid = profileID },
    commandType: CommandType.StoredProcedure).FirstOrDefault();

    return profile;
    }
    catch (Exception ex)
    {
    ErrorLogging.Instance.Fatal(ex); // use singleton for logging
    return null;
    }
    }
    }

    因此,将 Dapper 与一些 EDMX 实体一起使用似乎是让事情顺利进行的好方法。我可能弄错了,但我不知道为什么 Microsoft 没有完全考虑这一点 - 不支持 OData 的复杂类型。

    --- 更新 ---

    所以当我在一个多月前提出这个问题时,我终于得到了微软的回应:

    We have done research on this and we have found that the Odata client library doesn’t support complex types. Therefore, I regret to inform you that there is not much that we can do to solve it.

    *Optional: In order to obtain a solution for this issue, you have to use a Xml to Linq kind of approach to get the complex types.

    Thank you very much for your understanding in this matter. Please let me know if you have any questions. If we can be of any further assistance, please let us know.

    Best regards,



    看起来很奇怪。

    关于entity-framework - 如何使用 WCF 数据服务/OData 从 sproc 使用复杂对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9996929/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com