处理的OData客户端上的动态属性(dealing with dynamic properties

2019-10-23 20:09发布

我有服务器和客户端上的以下类

public class Entity
{
    public string Id {get; set;}
    public string Name {get; set;}
    public Dictionary<string, object> DynamicProperties {get; set;}
}

据我所看到开放式的所有示例介绍了有关在服务器端具有动态特性,但在客户端上的属性必须明确declared.When我发送来自客户端的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.
                });
            }
        });
    }

我得到一个错误,说明名为“IntProp”多个属性中的条目或复数值进行检测。 在OData的,重复的属性名称是不允许的 。 另外,我怀疑,如果发送对象怎么样我现在做的是一个有效的方法,因为我来自一个源获取大量的对象之前创建一个动作每一个时间,我把它发送到服务器。 如果我为每个对象创建一个动作,然后为客户端的OData在内存中保存这些行动可能炸毁内存。 如何处理我的情况? 请帮帮我。

此外,还有一个问题,如果我评论的container.Customers.ToList()失败,说明我试图添加未声明的属性。 这是为什么 ?

Answer 1:

如果您使用的OData客户端代码生成器 ,你可以使用partial class定义/检索/保存dyanmic性能。

例如,在您的客户端,您可以定义一个局部类的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();

对于类似的实现,你可以参考我的样本项目 。

==========迭代2 ================

对于客户端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是一个扩展方法。 你可以找到我的样本项目和最新提交

此外,引擎盖方法只适用于OData的客户端V6.12以上。

希望它可以帮助你。

==========迭代3 ================

  1. 首先,你可以调用下面的方法,

    container.Configurations.RequestPipeline.OnEntryStarting(...);

    这意味着增加,这将在以后的执行被称为动作。 在你的代码,你把它的两倍,因此,有添加了两个动作。 这两个动作将一个被称为一个当执行保存您的newCustomer1这就是, newCustomer1将有newCustomer的动态特性(行动1),同时,也将拥有自己的动态属性(行动2)。 这就是为什么你有重复的属性名例外。

要解决这个问题,你可以续订Container 。 见我的项目的更新。

  1. 对于container.Customers.ToList()它似乎是一个OData的客户问题。


Answer 2:

[回答我的问题: 另一种方法 ]

扩展萨姆徐的做法迭代2.我们可以如下做到这一点。 (为了清楚起见,让我们有问题的图书假设类的名称)

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
         });
      }
    }
 });

AddProperties扩展方法实现在山姆许的实现提供



文章来源: dealing with dynamic properties on oData client