第一步:定义实体类,注意DataServiceKeyAtrribute特性
[DataServiceKey("Id")]
public class Phone
{
public int Id
{
get;
set;
}
public string Number
{
get;
set;
}
public Student Stu
{
get;
set;
}
}
[DataServiceKey("Id")]
public class Student
{
public int Id
{
get;
set;
}
public string Name
{
get;
set;
}
public string Address
{
get;
set;
}
public IList<Phone> Phones
{
get;
set;
}
}
第二步:定义服务端Context,如果要使自定义的Conetxt能够执行CRUD,就必须实现 IUpdatable 接口;如下
public class StudentContext : IUpdatable
{
static IList<Student> _students;
static IList<Phone> _phones;
static StudentContext()
{
_students = new List<Student>()
{
new Student(){Id=1,Name="Stu 1",Address="xxxxxxx",Phones = new List<Phone>()},
new Student(){Id=2,Name="Stu 2",Address="xxxxxxx",Phones = new List<Phone>()},
};
_phones = new List<Phone>()
{
new Phone(){Id=1,Number="110"},
new Phone(){Id=2,Number="119"},
new Phone(){Id=3,Number="120"},
};
_students[0].Phones.Add(_phones[0]);
_phones[0].Stu = _students[0];
_students[0].Phones.Add(_phones[1]);
_phones[1].Stu = _students[0];
_students[1].Phones.Add(_phones[2]);
_phones[2].Stu = _students[1];
}
public IQueryable<Student> Students
{
get
{
return _students.AsQueryable<Student>();
}
}
public IQueryable<Phone> Phones
{
get
{
return _phones.AsQueryable<Phone>();
}
}
public object CreateResource(string containerName, string fullTypeName)
{
Type t = Type.GetType(fullTypeName, true);
object resource = Activator.CreateInstance(t);
if (containerName == "Students")
{
_students.Add(resource as Student);
}
if (containerName == "Phones")
{
_phones.Add(resource as Phone);
}
return resource;
}
public void DeleteResource(object targetResource)
{
if (targetResource.GetType() == typeof(Student))
{
_students.Remove(targetResource as Student);
return;
}
if (targetResource.GetType() == typeof(Phone))
{
_phones.Remove(targetResource as Phone);
}
throw new NotSupportedException("Type not found");
}
public object GetResource(IQueryable query, string fullTypeName)
{
object resource = query.Cast<object>().SingleOrDefault();
// fullTypeName can be null for deletes
if (fullTypeName != null && resource.GetType().FullName != fullTypeName)
{
throw new ApplicationException("Unexpected type for this resource.");
}
return resource;
}
public object GetValue(object targetResource, string propertyName)
{
// get the property info using reflection
var targetType = targetResource.GetType();
var targetProperty = targetType.GetProperty(propertyName);
// retrun the value of the property
return targetProperty.GetValue(targetResource, null);
}
public void SetValue(object targetResource, string propertyName, object propertyValue)
{
// get the property info using reflection
Type targetType = targetResource.GetType();
PropertyInfo property = targetType.GetProperty(propertyName);
// set the property value
property.SetValue(targetResource, propertyValue, null);
}
public object ResetResource(object resource)
{
return resource;
}
public object ResolveResource(object resource)
{
return resource;
}
public void SaveChanges()
{
// object in memory - do nothing
}
public void ClearChanges()
{
throw new NotImplementedException();
}
public void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
{
PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
if (pi == null)
throw new Exception("Can't find property");
IList collection = (IList)pi.GetValue(targetResource, null);
collection.Add(resourceToBeAdded);
}
public void SetReference(object targetResource, string propertyName, object propertyValue)
{
((IUpdatable)this).SetValue(targetResource, propertyName, propertyValue);
}
public void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
{
PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
if (pi == null)
throw new Exception("Can't find property");
IList collection = (IList)pi.GetValue(targetResource, null);
collection.Remove(resourceToBeRemoved);
}
}
第三步:创建一个Web Application 项目,添加一个WCF Data Service项(比如我们取名为“StudentDataService”),CS代码如下;
public class StudentDataService : DataService<StudentContext>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
// Examples:
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
注意:泛型参数为之前我们定义的Context,InitializeService方法内部的前两行代码用以设置Client端调用的权限,我们设置为对所有的数据(*)拥有所有权限。
我们把StudentDataService.svc部署到IIS,假设URL为"http://localhost:/StudentDataService.svc/"
第四步:客户端调用,可以添加Service References,共享服务器端实体类,也可以在客户端定义和服务器端相同的实体类(Phone 和 Student),注意要和服务器端一致;示 例 如下:
Uri uri = new Uri(@"http://localhost:52758/StudentDataService.svc/");
DataServiceContext ctx = new DataServiceContext(uri);
DataServiceQuery<Student> query = ctx.CreateQuery<Student>("Students");
var stu = query.FirstOrDefault();
Phone phone = new Phone() { Id = 4, Number = "140" };
Phone phone1 = new Phone() { Id = 5, Number = "150" };
ctx.AddRelatedObject(stu, "Phones", phone);
ctx.SetLink(phone, "Stu", stu);
ctx.AddRelatedObject(stu, "Phones", phone1);
ctx.SetLink(phone1, "Stu", stu);
ctx.SaveChanges();
更多关于Odata的了解请Email我:KKevinn@126.com