2016-02-23 85 views
0

一起考慮以下實體Asp.Net的WebAPI的OData V4 - 保存實體與相關實體

public class Supplier 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public ICollection<Product> Products { get; set; } 
} 

public class Product 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public decimal Price { get; set; } 
    public string Category { get; set; } 

    public int? SupplierId { get; set; } 
    public virtual Supplier Supplier { get; set; } 
} 

由於每供應商的實體上面的代碼可以有零個或更多產品。 在上述實體中,ID是由實體框架自動生成的。

我使用OData的V4客戶端代碼生成器。

客戶端代碼:

Supplier s = new Supplier{...} 
OdataContext.AddToSuppliers(s); 

Product p = new Product{...} 
p.SupplierId = s.Id; 
OdataContext.AddToProduct (p); 

OdataContext.SaveChanges(); 

供應商控制器:

public async Task<IHttpActionResult> Post(Supplier supplier) 
{ 
    if (!ModelState.IsValid) 
    { 
     return BadRequest(ModelState); 
    } 
    db.Supplier.Add(supplier); 
    await db.SaveChangesAsync(); 
    return Created(supplier); 
} 

產品控制器:

public async Task<IHttpActionResult> Post(Product product) 
{ 
    if (!ModelState.IsValid) 
    { 
     return BadRequest(ModelState); 
    } 
    db.Products.Add(product); 
    await db.SaveChangesAsync(); 
    return Created(product); 
} 

當我保存我收到一條錯誤消息的變化:

INSERT語句衝突與外鍵約束。

錯誤的原因是Product實體沒有SupplierId還沒有它作爲數據庫生成的密鑰。

所以,我怎麼能添加SupplierIdProduct實體在保存記錄? 任何人都可以幫我解決這個問題嗎?

回答

0

OK,感謝澄清。假設您正在使用SQL Server,則您的Int Id列將按照慣例成爲標識列。從這個角度看,產品可以有0個或1個供應商。

要將新產品添加到一個新的供應商,你可以這樣做:

Supplier s = new Supplier 
{ 
    Name = "mySupplier" 
} 

Product p = new Product 
{ 
    Name = "myname", 
    Price = 123.45, 
    Category = "myCategory", 
    Supplier = s 
} 

OdataContext.Products.Add(p); 
OdataContext.SaveChanges(); 

要將現有的供應商增加產品:

// select a supplierId or search by name 
var supplier = OdataContext.Suppliers.FirstOrDefault(s => s.Name == nameToFind); 
if (supplier == null) // Handle no match 

Product p = new Product 
{ 
    Name = "myname", 
    Price = 123.45, 
    Category = "myCategory", 
    SupplierId = supplier.Id 
} 

OdataContext.Products.Add(p); 
OdataContext.SaveChanges(); 
+0

是的,我同意,這個問題是錯誤的。現在我編輯了這個問題。在你的例子中,你是這樣做的:'s.ProductId = p.ProductId;'據我所知,仍然'p.ProductId'沒有正確的值?那麼這個任務如何工作?它會從數據庫序列獲得價值嗎?你能解釋一下嗎? – Rahul

+0

我修改了代碼並運行解決方案,但仍然收到相同的錯誤。 > INSERT語句與FOREIGN KEY約束「FK_dbo.Product_dbo.Supplier_SupplierId」衝突。數據庫「DBContext」,表「dbo.Supplier」,列'Id'發生衝突。 該聲明已被終止。我調試並注意到供應商是在數據庫中創建的,而不是產品。 – Rahul

0

我想的OData客戶端將不支持深插入呢。因此,另一種選擇是使用WebClient和JSON序列化程序作爲請求主體,如下所示。父母和子女有實體將在HTTP請求中創建和外鍵將得到相應的更新 -

var product = new ProductService.Models.Product() 
     { 
      Name = "My Car", 
      Category = "Auto", 
      Price = 4.85M 
     }; 

     var supplier = new ProductService.Models.Supplier() 
     { 
      Name = "My Name" 
     }; 

     //Add product to supplier 
     supplier.Products.Add(product); 

     WebClient client = new WebClient(); 
     client.BaseAddress = "http://example.com/OData"; 
     client.Headers.Add("Content-Type", "application/json"); 

     //Serialize supplier object 
     var serializer = new JavaScriptSerializer(); 
     var serializedResult = serializer.Serialize(supplier); 

     //Call the service 
     var result = client.UploadString("http://example.com/OData/Suppliers", serializedResult.ToString()); 

行動後在供應商控制器 -

public async Task<IHttpActionResult> Post(Supplier supplier) 
    { 
     if (!ModelState.IsValid) 
     { 
      return BadRequest(ModelState); 
     } 
     db.Suppliers.Add(supplier); 
     await db.SaveChangesAsync(); 
     return Created(supplier); 
    } 
相關問題