zoukankan      html  css  js  c++  java
  • MOSS 2010:Visual Studio 2010开发体验(22)——利用BCS和WCF进行应用程序集成

    上一篇,我们讲到了如何利用BCS服务,直接连接到SQL Server数据库实现一些简单的应用程序集成的场景。看起来很不错,不是吗?

    但是,事实上,直接连接到数据库也许有时候是不可能实现的任务,很多系统并不可能直接将数据库暴露出来的。地球人都知道,那样的风险极高。

    那么,比较可行的是什么方式呢?我觉得很多系统倒是有公开一些服务,这些服务有的使用Web Service实现,有的不是。这都不要紧。总之,由这些服务去连接数据库,而我们做集成的时候,并不需要知道数据库在哪里?以及什么结构等等信息。

    这一篇,我们讲解使用WCF作为服务,实现应用程序集成的简单步骤

    1. 创建一个测试用的服务

    为了快速开发,我们会将该服务宿主在一个Web Application中,所以首先我们需要创建这个Application

    image

    默认会有下面这样的项目结构

    image

    我们无需修改default.aspx.因为我们根本不使用它

    为了读取数据库,我们可以创建一个LINQ to SQL数据模型

    image

    image

    我们可以将Northwind数据库的连接定义在Server Explorer中,并且将Employees表拖拽到这个设计器中来

    image

    保存该模型。下面我们就来添加我们的服务了

    image

    image

    修改这个IEmployeeService成下面这样

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace NorthwindService
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IEmployeeService" in both code and config file together.
        [ServiceContract]
        public interface IEmployeeService
        {
            [OperationContract]
            Employee[] GetEmployeeList();
    
            [OperationContract]
            Employee GetEmployeeItem(int id);
        }
    }
    

    image

    接下来修改EmployeeService.svc.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace NorthwindService
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "EmployeeService" in code, svc and config file together.
        public class EmployeeService : IEmployeeService
        {
    
            public Employee[] GetEmployeeList()
            {
                NorthwindDataContext context = new NorthwindDataContext();
                return context.Employees.ToArray();
            }
    
            public Employee GetEmployeeItem(int id)
            {
                NorthwindDataContext context = new NorthwindDataContext();
                return context.Employees.FirstOrDefault(e => e.EmployeeID == id);
            }
        }
    }
    

    image

    这样就好了,下面我们可以测试该服务了

    选中“EmployeeService.svc”这个文件,右键,

    image

    如果看到下面这样的界面,则基本上是表示服务创建没有什么大的问题

    image

    点击http://localhost:8027/EmployeeService.svc?wsdl这个链接

    image

    我们可以用一个工具来测试一下到底能不能返回正确的结果

    image

    image

    点击“File”=》”Add Service”,然后输入服务地址

    image

    【注意】你的地址可能和我不一样,主要检查端口号

    image

    双击GetEmployeeItem,输入一个id的值(例如10),然后点击 ”Invoke“按钮

    image

    好,如果是这样的话,则表示该服务是能够正常工作的。

    2. 创建BCS 内容类型,使用该服务

    既然服务准备好了,下面我们就来看看如何在BCS外部内容类型中使用该服务

    首先,仍然是在下面的界面中,点击左上角的 “External Content Type”按钮

    image

    然后做一些必要的修改,使界面看起来像下面这样

    image

    仍然是点击”Click here to discover external data sources …“

    image

    再次点击 “Add Connection”

    image

    将Type设置为WCF Service

    image

    Ooooop ,我收到了一个错误

    image

    它的意思是说,不能使用localhost这个写法。好吧,我们从善如流吧。我们可以将网站发布到IIS

    image

    【注意】这个发布向导是VS2010新增的,还可以

    发布之后,应该可以看到IIS中如下的效果

    image

    然后,我们确认在浏览器中,可以通过下面的地址访问到服务

    http://nymoss2010/NorthwindServices/EmployeeService.svc

    image

    修改下面的地址

    image

    但是却仍然是报告错误

    image

    My God !太伤心了 好吧,再大的困难也难不倒英雄的中华儿女们。为了排除到底是不是IIS的问题,我们可以单独来做一个宿主好了。

    image

    添加引用

    image

    image

    在Main方法中编写如下代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using NorthwindService;
    using System.ServiceModel.Description;
    
    namespace EmployeeServiceHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (ServiceHost host = new ServiceHost(
                    typeof(EmployeeService), new Uri("http://nymoss2010/NorthwindService")))
                {
                    host.AddServiceEndpoint(
                        typeof(IEmployeeService).FullName,
                        new BasicHttpBinding(),
                        "");
    
    
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    host.Description.Behaviors.Add(behavior);
    
                    host.AddServiceEndpoint(
                        "IMetadataExchange",
                        MetadataExchangeBindings.CreateMexHttpBinding(),
                        "mex");
    
                    host.Open();
                    Console.WriteLine("Server is ready");
                    Console.Read();
    
                }
            }
        }
    }
    

    同时,在这个宿主中添加一个配置文件app.config,编辑内容如下

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <connectionStrings>
        <add name="NorthwindConnectionString" connectionString="Data Source=(local);Initial Catalog=Northwind;Integrated Security=True"
            providerName="System.Data.SqlClient" />
      </connectionStrings>
    </configuration>

    将该程序启动为调试状态

    image

    然后可以通过下面地址访问到该服务

    image

    然后再去添加该服务吧

    image

    【注意】Service Metadata URL是有一个?wsdl的后缀的

    image

    【注意】我们发现现在是可以了。所以刚才那个应该是IIS某些地方出了问题,也可能是因为beta版的缘故吧。暂时不理会它。

    选中 “GetEmployeeList”,右键,选择”New Read List Operation“

    image

    image

    点击Next

    image

    继续Next

    image

    选中”EmployeeId“,将其Map toIdentifier

    image

    点击Finish完成该Operation的定义

    image

    然后,我们再 选中GetEmployeeItem,右键,New Read Item Operation

    image

    image

    image

    【注意】这里也需要Map to identifier

    image

    image

    保存(CTRL+S) ,然后点击“Create Lists & Form”按钮

    image

    创建成功之后,我们兴冲冲地去网页中查看这个列表,却发现如下的错误

    image

    这是好事多磨啊,啊  focus,focus……. 继续排除错误

    我用之前用过的一个工具,来确认一下方法哪里出了问题。我发现果然是那个GetEmployeeList出现了问题

    image

    但是,GetEmployeeitem却是可以返回的

    image

    那么,这说明什么问题呢?我联想到员工表是有一个相片字段的,而相片的长度是很长的,应该是总的数据量超过了WCF的默认限制(64KB)所导致的问题

    为了验证我的想法,我修改一下源代码

            public Employee[] GetEmployeeList()
            {
                //NorthwindDataContext context = new NorthwindDataContext();
                //return context.Employees.ToArray();
                return new Employee[]{
                    new Employee(){EmployeeID=1,FirstName="Ares",LastName="Chen"}
                };
            }
    

    然后再测试

    image

    现在就可以正常返回了。所以,我们如果回到网页中去,刷新列表,应该也是可以的

    image 

    image

    为了避免图片导致数据太大,我们修改了代码如下。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace NorthwindService
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "EmployeeService" in code, svc and config file together.
        public class EmployeeService : IEmployeeService
        {
    
            public Employee[] GetEmployeeList()
            {
                NorthwindDataContext ctx = new NorthwindDataContext();
                List<Employee> result = new List<Employee>();
                foreach (var e in ctx.Employees)
                {
                    result.Add(new Employee
                            {
                                EmployeeID = e.EmployeeID,
                                FirstName = e.FirstName,
                                LastName = e.LastName,
                                Country = e.Country,
                                Region = e.Region,
                                City = e.City
                            });
    
                }
                return result.ToArray();
    
            }
    
            public Employee GetEmployeeItem(int id)
            {
                NorthwindDataContext context = new NorthwindDataContext();
                var e = context.Employees.FirstOrDefault(emp => emp.EmployeeID == id);
    
                return new Employee
                            {
                                EmployeeID = e.EmployeeID,
                                FirstName = e.FirstName,
                                LastName = e.LastName,
                                Country = e.Country,
                                Region = e.Region,
                                City = e.City
                            };
    
                           
                
            }
        }
    }
    

    image

    image

    【注意】当然,有可以通过调整WCF的binding的一些参数来让它可以传输更多数据量,那属于是WCF本身的技术。大家有兴趣可以参考一下

    http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpbinding.maxbuffersize.aspx

    总结:这一篇文章讲解了如何结合WCF技术实现应用程序集成设计。这是比直接访问数据库要灵活得多的一种方案。

    如你所见,我在写这个文档的时候,估计暴露出来了一些错误的场景,这可以帮助大家更好地学习和掌握有关的技术。

  • 相关阅读:
    Java架构师必知:什么是单点登录,主要会应用于哪些场景?
    15年老程序员首次分享,年薪200万是怎么做到的
    架构师进阶之路,什么人适合当架构师
    阿里大咖首次分享:软件工程危机真来了?
    用【快餐店】理解日均亿级高并发分布式架构,秒懂!
    Semi-supervised learning for Text Classification by Layer Partitioning
    Ordered Neurons: Integrating Tree Structures Into Recurrent Neural Networks
    Deep Learning Recommendation Model for Personalization and Recommendation Systems
    条件随机场
    隐马尔可夫模型
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1725576.html
Copyright © 2011-2022 走看看