踩坑(Running)填坑(ZSSURE):WCF技术初步应用

背景:

近期由于项目需要,开始学习和使用WCF技术。初次涉猎一种陌生技术领域,最常见的就是踩“坑”了。之前在博客园浏览了WCF专家老A的博文,并且翻阅了其相关著作《WCF技术剖析》和《WCF全面解析》。但是在项目实际开发过程中,还是遇到了这样和那样的问题。一次踩到如此多的“坑”,让我很震惊。因此决定在博客中开辟“踩坑填坑”系列博文,该类博文主要用于记录在运用新技术开发过程中遇到的各种奇葩错误,同时直接给出解决方案。然文中却不会对问题的根源和解决方案进行详细介绍,待后续有时间深入研究分析相关问题机理后再统一发文归类到“日积月累”系列中。

踩坑&填坑:

【踩坑】:基于Object的ServiceHost创建

踩坑(Running)填坑(ZSSURE):WCF技术初步应用_第1张图片

【填坑】:

由于WCF服务的宿主选用的是WinForm程序,所以需要在WCFServiceLib类库中回调WinForm的函数进行界面刷新等操作,因此在构造ServiceHost对象时,采用的是
public ServiceHost(object singletonInstance, params Uri[] baseAddresses);
利用该构造函数时,要求在服务契约ServiceContract中添加行为约束,即InstanceContextMode=InstanceContextMode.Single。上述错误提示已经很明确的指出了解决方案。具体的实例可以参考之前的博文。

【踩坑】:ServiceContract的继承?

踩坑(Running)填坑(ZSSURE):WCF技术初步应用_第2张图片

【填坑】:

WCF具体实现过程会将服务契约以接口形式给出,并添加ServiceContract、OperationContract等属性约束。然后通过实现该接口来完成具体的WCF服务定义。此时需要注意的是WCF具体实现类中不需要添加ServiceContract、OperationContract等配置约束。否则会弹出上述错误提示。
简单的给出一段示例代码:

//服务契约的约定接口类
[ServiceContract]
public interface IWcfServiceTest
{
    [OperationContract]
    void wcfHelloWorld(string name);
}
//服务契约的具体实现类
public class WcfServiceTest:IWcfServiceTest
{
    void wcfHelloWorld(string name)
    {
        Console.WriteLine(name+":HellowWorld");
    }
}

【踩坑】:OperationContract的继承?

踩坑(Running)填坑(ZSSURE):WCF技术初步应用_第3张图片

【填坑】:

与上面的ServiceContract坑类似,OperationContract在WCF服务具体实现类中也不需要重复设置。示例代码如上述相同。

【踩坑】:DataContract中枚举变量

踩坑(Running)填坑(ZSSURE):WCF技术初步应用_第4张图片

【填坑】:

在WCF中需要定义数据契约(Data Contract),简而言之就是通知服务双方,在调用具体服务函数时如何来序列化参数。对于枚举类型的成员,需要额外注意一下。具体的实现方式是:

namespace WCFData
{
     [DataContract]
     public enum WCFEnum
     {
        [EnumMemeber]
        WcfCFind=0,
        [EnumMemeber]
        WcfCStore=1,
        [EnumMemeber]
        WcfCMove=2
     }
     [DataContract]
     public class WCFRequest
     {
        [DataMember]
        public string PatientID{get;set;}
        [DataMemeber]
        public string PatientName{get;set;}
        [DataMember]
        public WCFEnum ReqType{get;set;]
     }
}

对于上述问题可参考下面两篇博文WCF枚举变量、WCF枚举变量2。

【踩坑】:Telerik OpenAccess与SQLite结合

Telerik与SQLite结合,可以顺利开发简单编写的应用。但是在使用SQLite引擎时往往会出现错误中断。提示你添加System.Data.SQLite.dll的引用,虽然你已经添加到了工程的“引用”中。

【填坑】:

经过仔细搜索Telerik官方资料,发现其中已经针对该问题给出了三种解决方案,具体的大家可以参照Telerik官方说明,这里我选择的是硬编码方式,具体代码如下:

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    if (args.Name.StartsWith("System.Data.SQLite,"))
    {
        return typeof(System.Data.SQLite.SQLiteFactory).Assembly;
    }
    return null;
}

【踩坑】:Telerik OpenAccess中如何提取新插入记录的主键PK值

在使用WinForm来寄宿WCF服务时,会遇到绑定事件来刷新界面的情况,具体可参考博文中的示例。另外有时候会需要对刚添加到数据库中的记录进行更新,这就需要获取记录的PK值,在Telerik官方论坛中搜索了半天未果。

【填坑】:

后来在具体尝试时发现,当调用SaveChanges()函数保存修改后,与刚插入的记录中的主键对应的对象的指定属性值就是数据库中该条记录的主键,即PK值。
示例代码如下:

//*********************Code First Model定义类*******************
public class Customer
{
   public int ID { get; set; }
   public string Name { get; set; }
   public DateTime DateCreated { get; set; }
   public string EmailAddress { get; set; }
}
//***************具体的映射关系,其中设置ID为主键****************
protected override IList<MappingConfiguration> PrepareMapping()
{
   List<MappingConfiguration> configurations = new List<MappingConfiguration>();

   var customerMapping = new MappingConfiguration<Customer>();
   customerMapping.MapType(customer => new
   {
   ID = customer.ID,
   Name = customer.Name,
   EmailAddress = customer.EmailAddress,
   DateCreated = customer.DateCreated
   }).ToTable("Customer");
   customerMapping.HasProperty(c => c.ID).IsIdentity();

   configurations.Add(customerMapping);

   return configurations;
}
public IQueryable<Customer> Customers
{
   get
   {
   return this.GetAll<Customer>();
   }
}

//*******************实际应用,Update更新数据库*********************
using (EntitiesModel dbContext = new EntitiesModel())
{
   // Update a category
   Category category = dbContext.Categories.First();
   category.CategoryName = "New Name";

   // Create two new categories
   Category newCategory1 = new Category();
   newCategory1.CategoryName = "New Category";
   Category newCategory2 = new Category();
   newCategory2.CategoryName = "New Category2";

   dbContext.Add(new Category[] { newCategory1, newCategory2 });
   dbContext.SaveChanges();
   //【zssure】:调用SaveChanges后数据库中已经完成插入操作,此时可以获取到刚刚插入的记录的主键ID值
   Console.WriteLine("Category1的PrimaryKey是{0},Category2的PrimaryKey是{1}",newCategory1.ID,newCategory2.ID);
}

ZSSURE:

踩坑(Running)填坑(ZSSURE),是近期由于项目中遇到了大量奇葩问题而新开的系列博文,主要用于记录开发过程中遇到的实际问题,并给出简单的解决方案,并保证方案在本人运行环境下成功。后续待慢慢沉淀积累后会对其中的重点问题进行剖析,并发文到“日积(Running)月累(ZSSURE)”系列。





作者:[email protected]
时间:2015-04-08

你可能感兴趣的:(WCF,WCF技术)