如何使用ODATA保存对象属性?

时间:2017-04-02 19:56:45

标签: c# odata

当我保存发票

时,我有这些课程
string serviceUri = "http://myserviceurl.azurewebsites.net/odata/";
var container = new Default.Container(new Uri(serviceUri));

var myInvoice = container.Invoice.Expand("CreatedBy").Where(x => x.Id == new Guid("B7E5EEAD-EA77-4174-8305-50440AD057C7")).Skip(0).First();
myInvoice.CreatedBy = container.User.First();
container.UpdateObject(myInvoice);

它保存了Invoice(字段:GUID,字符串),但是 CreatedBy 用户字段没有保存(它没有发送到服务器,在服务器端我检查了它并且

如何修复它,或者它是ODATA 4中的限制?

我应该只将ODATA用于读取; 并创建另一个WebApi来保存整个发票实体(包括CreatedBy)?评论,解决方案将不胜感激。

[PropertyChanged.ImplementPropertyChanged]
public class User
{
    [Index]
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public string Name { get; set; }
}

[PropertyChanged.ImplementPropertyChanged]
public class Invoice
{
    [Index]
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public User CreatedBy { get; set; }    // how to save this?

    [InverseProperty("Invoice")]
    public ICollection<InvoiceItem> Items { get; set; }    // how to save this?
 }

[PropertyChanged.ImplementPropertyChanged]
public class InvoiceItem
{
    [Index]
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public Invoice Invoice { get; set; }

    public decimal Qty { get; set; }
    public decimal Price { get; set; }
    public decimal Total { get; set; }
}

在这些情况下,ODATA是否仅适用于READ?要写,我应该写自己的WebApi? 这样的事情:(或者可能是这个的通用版本)

public void Post([FromBody] Invoice p)
{
    SyncContext db = new SyncContext();

    db.Entry(p).State = System.Data.Entity.EntityState.Modified; // Exists?

    foreach (var item in p.Items)
    {
        var f = db.InvoiceItem.Where(i => i.Id == item.Id).FirstOrDefault();
        db.Entry(item).State = f == null ?
                            System.Data.Entity.EntityState.Added :
                            System.Data.Entity.EntityState.Modified;
    }

    db.SaveChanges();
}

客户方:

using (var client = new WebClient())
{
    var dataString = JsonConvert.SerializeObject(myInvoice);
    client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
    client.UploadString(new Uri("http://localhost:56948/odata/Invoice"), "POST", dataString);
}

2 个答案:

答案 0 :(得分:1)

您需要将用户添加为发票的外键。由于您的用户ID是由数据库创建的,因此您需要先创建用户。

[示例](https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/entity-relations-in-odata-v4

public class Invoice
{
    ...
    // New code:    
    [ForeignKey("User")]
    public Guid userId { get; set; }
    public virtual User User { get; set; }
}

答案 1 :(得分:0)

经过几天调查这个问题,并尝试使用一些库,在ODATA 3,ODATA 4,甚至MongoDB和DocumentDB上, 我可以说这个问题是由系统进入和存储数据的深度问题引起的。根据保存的对象,可以通过发票上的简单保存来访问几乎整个数据库。

我认为可以做的是在 CreatedBy 中实现 [NotRecursive] 这样的注释,

因此它只会发送该属性的密钥,而不是整个 CreatedBy(用户)图。

另一种可能的数据注释是 [RecursiveLevel(NumberOfLevels)]

这个递归问题会影响它们:Entity,NHibernate,ODATA,甚至像MongoDB和DocumentDB这样的Document存储。

需要创建一个简单的规范(Data Annotation)来解决这个嵌套级别定义,以便在各种数据库和ORM / Mapper上进行保存。