【问题标题】:dealing with dynamic properties on oData client处理 oData 客户端上的动态属性
【发布时间】:2015-10-02 06:53:20
【问题描述】:

我在服务器和客户端都有以下课程

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

据我所见,开放类型的所有示例都描述了在服务器端具有动态属性,但客户端上的属性需要显式声明。当我从客户端发送 POST 请求时,我该如何发送动态属性 ?.我无法在客户端声明所有动态属性。有许多属性,每个对象将在客户端包含不同的动态属性集。这些动态属性存储在客户端的 DynamicProperties 字典中。如何将上述实体类的对象发送到服务器端,以便服务器将 DynamicProperties 字典的内容解释为动态属性?任何帮助表示赞赏。

============================跟进sam的回答=========== ============

    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() 发表评论,还有一个问题,表明我正在尝试添加未声明的属性。这是为什么呢?

【问题讨论】:

    标签: c# asp.net-web-api odata asp.net-web-api2


    【解决方案1】:

    如果您使用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();
    }
    

    然后,您可以使用它来插入/检索/保存动态属性“Email”。

    你可以这样做:

    Container container = new Container(new Uri("http://..."));
    Entity entity = new Entity();
    ...
    entity.Email = "xxxx";
    container.AddToEntities(entity);
    container.SaveChanges();
    

    类似的实现,可以参考my sample project

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

    对于带有IDictionary&lt;string,object&gt; 的客户端Entity 类,我认为钩子正是您要找的。​​p>

    例如,在客户端:

    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

    此外,hood 方法仅适用于 OData Client V6.12 或更高版本。

    希望对你有帮助。

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

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

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

      这意味着添加一个将在以后执行时调用的动作。在您的代码中,您调用了两次,因此添加了 两个 操作。这两个动作会在执行时一一调用来保存你的newCustomer1 也就是说,newCustomer1 将拥有newCustomer 的动态属性(动作 1),同时,它将拥有自己的动态属性(动作 2)。这就是为什么出现重复属性名称异常的原因。

    要解决它,您只需更新Container。查看我的项目更新。

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

    【讨论】:

    • 山姆,非常感谢您的回答。我的要求是我不能申报财产。在上面的示例中,电子邮件是在 Entity 类中声明的。在客户端,我的 Entity 类结构与服务器端相同,属性电子邮件将位于客户端的 DynamicProperties 字典中,我想将这些动态属性发送到服务器端。我怎么做 ?。 (我已经编辑了问题以反映这一点)
    • @Prashanth 我更新了我的答案。希望它可以提供帮助。任何其他问题或问题,请告诉我们。
    • 再次感谢。但是我面临这种方法的问题,因为实体的每个对象的动态属性字典将具有不同的键。我已经编辑了这个问题并发布了一个后续问题。请检查一下。
    • @sam,再次感谢 :)
    • Iteration 1 解决方案对我不起作用。参数在 HTTP 负载中发送,但在服务器端,DynamicProperties 字典中没有接收到参数。
    【解决方案2】:

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

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

    AddProperties在 Sam Xu 的实现中提供了扩展方法实现

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多