近期由于项目需要,开始学习和使用WCF技术。初次浏览1种陌生技术领域,最多见的就是踩“坑”了。之前在博客园阅读了WCF专家老A的博文,并且翻阅了其相干著作《WCF技术剖析》和《WCF全面解析》。但是在项目实际开发进程中,还是遇到了这样和那样的问题。1次踩到如此多的“坑”,让我很震惊。因此决定在博客中开辟“踩坑填坑”系列博文,该类博文主要用于记录在应用新技术开发进程中遇到的各种奇葩毛病,同时直接给出解决方案。然文中却不会对问题的本源和解决方案进行详细介绍,待后续有时间深入研究分析相干问题机理后再统1发文归类到“日积月累”系列中。
由于WCF服务的宿主选用的是WinForm程序,所以需要在WCFServiceLib类库中回调WinForm的函数进行界面刷新等操作,因此在构造ServiceHost对象时,采取的是
public ServiceHost(object singletonInstance, params Uri[] baseAddresses);
利用该构造函数时,要求在服务契约ServiceContract中添加行动束缚,即InstanceContextMode=InstanceContextMode.Single。上述毛病提示已很明确的指出了解决方案。具体的实例可以参考之前的博文。
WCF具体实现进程会将服务契约以接口情势给出,并添加ServiceContract、OperationContract等属性束缚。然后通过实现该接口来完成具体的WCF服务定义。此时需要注意的是WCF具体实现类中不需要添加ServiceContract、OperationContract等配置束缚。否则会弹出上述毛病提示。
简单的给出1段示例代码:
//服务契约的约定接口类
[ServiceContract]
public interface IWcfServiceTest
{
[OperationContract]
void wcfHelloWorld(string name);
}
//服务契约的具体实现类
public class WcfServiceTest:IWcfServiceTest
{
void wcfHelloWorld(string name)
{
Console.WriteLine(name+":HellowWorld");
}
}
与上面的ServiceContract坑类似,OperationContract在WCF服务具体实现类中也不需要重复设置。示例代码如上述相同。
在WCF中需要定义数据契约(Data Contract),简而言之就是通知服务双方,在调用具体服务函数时如何来序列化参数。对枚举类型的成员,需要额外注意1下。具体的实现方式是:
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与SQLite结合,可以顺利开发简单编写的利用。但是在使用SQLite引擎时常常会出现毛病中断。提示你添加System.Data.SQLite.dll的援用,虽然你已添加到了工程的“援用”中。
经过仔细搜索Telerik官方资料,发现其中已针对该问题给出了3种解决方案,具体的大家可以参照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;
}
在使用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);
}
踩坑(Running)填坑(ZSSURE),是近期由于项目中遇到了大量奇葩问题而新开的系列博文,主要用于记录开发进程中遇到的实际问题,并给出简单的解决方案,并保证方案在本人运行环境下成功。后续待渐渐沉淀积累后会对其中的重点问题进行剖析,并发文到“日积(Running)月累(ZSSURE)”系列。
作者:zssure@163.com
时间:2015-04-08
上一篇 四城市十行业紧缺人才信息公布
下一篇 下一波浪潮物联网什么时候才能到来