我在服务器和客户端上都有以下类
public class Entity
{
public string Id {get; set;}
public string Name {get; set;}
public Dictionary<string, object> DynamicProperties {get; set;}
}
据我所知,open类型的所有示例都描述了在服务器端具有动态属性,但是客户端上的属性需要显式声明。当我从客户端发送POST请求时如何发送动态属性?我无法在客户端声明所有动态属性。有许多属性,每个对象将在客户端包含不同的动态属性集。这些动态属性存储在客户端的DynamicProperties字典中。如何将上述实体类的对象发送到服务器端,以便服务器将DynamicProperties字典的内容解释为动态属性?任何帮助表示赞赏。
===========================对山姆回答的跟进======= ================
static void Main(string[] args1)
{
container.Customers.ToList();
Customer newCustomer = new Customer();
newCustomer.Id = 19;
newCustomer.Properties = new Dictionary<string, object>
{
{"IntProp", 9},
{"DateTimeOffsetProp", new DateTimeOffset(2015, 7, 16, 1, 2, 3, 4, TimeSpan.Zero)},
{"blah","ha"}
};
try
{
addCustomer(newCustomer);
container.AddToCustomers(newCustomer);
container.SaveChanges();
}
catch (Exception)
{
}
Customer newCustomer1 = new Customer();
newCustomer1.Id = 20;
newCustomer1.Properties = new Dictionary<string, object>
{
{"IntProp", 10},
{"dir","north"}
};
addCustomer(newCustomer1);
container.AddToCustomers(newCustomer1);
container.SaveChanges();
newCustomer1.Properties["dir"] = "south";
container.UpdateObject(newCustomer1);
container.SaveChanges();
Console.ReadKey();
}
private static void addCustomer(Customer customer)
{
container.Configurations.RequestPipeline.OnEntryStarting(args =>
{
foreach (var property in customer.Properties)
{
args.Entry.AddProperties(new ODataProperty
{
Name = property.Key,
Value = property.Value // for enum, complex type, should to create ODataEnumValue and ODataComplexValue.
});
}
});
}
我收到一条错误,指出多个属性名称为&#39; IntProp&#39;在条目或复杂值中检测到。在OData中,不允许重复的属性名称。另外,我怀疑每次在发送一个对象之前创建一个动作,就像我现在正在做的那样是一种有效的方法,因为我从源中获取了大量对象并将其发送到服务器。如果我为每个对象创建一个动作,那么当oData客户端在内存中保存这些动作时,它可能会炸毁内存。我该如何处理我的场景?请帮助我。
另外,还有一个问题,如果我评论 container.Customers.ToList(),它会失败,说明我正在尝试添加未声明的属性。那是为什么?
答案 0 :(得分:0)
如果您使用的是OData Client Code Generator,则可以使用partial class
来定义/检索/保存动态属性。
例如,在您的客户端,您可以为Entity
public partial class Entity
{
// Dynamic property "Email"
[global::Microsoft.OData.Client.OriginalNameAttribute("Email")]
public string Email
{
get
{
return this._Email;
}
set
{
this.OnEmailChanging(value);
this._Email = value;
this.OnEmailChanged();
this.OnPropertyChanged("Email");
}
}
private string _Email;
partial void OnEmailChanging(string value);
partial void OnEmailChanged();
}
然后,您可以使用它来插入/检索/保存动态属性“电子邮件”。
你可以这样做:
Container container = new Container(new Uri("http://..."));
Entity entity = new Entity();
...
entity.Email = "xxxx";
container.AddToEntities(entity);
container.SaveChanges();
对于类似的实施,您可以参考my sample project。
对于Entity
的客户IDictionary<string,object>
班级,我认为您正在寻找钩子。
例如,在客户端:
public partial class Entity
{
public IDictionary<string, object> Properties { get; set; }
.....
}
如果在
之前插入以下代码,它应该有效 container.AddToEntities(entity);
例如:
Entity entity = new Entity();
...
entity.Properties = new Dictionary<string, object>
{
{"IntProp", 9},
{"DateTimeOffsetProp", new DateTimeOffset(2015, 7, 16, 1, 2, 3, 4, TimeSpan.Zero)}
};
container.Configurations.RequestPipeline.OnEntryStarting(args =>
{
foreach (var property in entity.Properties)
{
args.Entry.AddProperties(new ODataProperty
{
Name = property.Key,
Value = property.Value
});
}
});
container.AddToEntities(entity);
container.SaveChanges();
其中,AddProperties
是一种扩展方法。你可以在my sample project找到它
和the latest commit
此外,引擎盖方法仅适用于 OData Client V6.12或更高版本。
希望它可以帮到你。
首先,您调用以下方法,
container.Configurations.RequestPipeline.OnEntryStarting(...);
这意味着添加将在以后执行中调用的操作。在您的代码中,您将其调用两次,因此,添加了两个操作。执行保存newCustomer1
时,将逐个调用这两个操作
那就是newCustomer1
将拥有newCustomer
的动态属性(动作1),同时,它将拥有自己的动态属性(动作2)。这就是为什么你得到重复的属性名称异常。
要解决此问题,您只需续订Container
即可。查看我的项目更新。
container.Customers.ToList()
,它似乎是OData客户端问题。 答案 1 :(得分:0)
[回答我自己的问题:另一种方法]
扩展Sam Xu的迭代方法2.我们可以这样做。 (为了清楚起见,我们假设所讨论的类的名称为Book)
public partial class Book
{
public string ISBN {get; set;}
public IDictionary<string, object> DynamicProperties { get; set; }
}
// This portion can be put in a function and can be invoked only once
container.Configurations.RequestPipeline.OnEntryStarting(args =>
{
if(args.Entity.GetType() == typeof(Book))
{
var book = args.Entity as Book
foreach (var property in book.DynamicProperties)
{
args.Entry.AddProperties(new ODataProperty
{
Name = property.Key,
Value = property.Value
});
}
}
});
Sam Xu的实现中提供了AddProperties 扩展方法实现