【问题标题】:Asp.Net WebApi OData v4 - Saving Entity along with related entitiesAsp.Net WebApi OData v4 - 保存实体以及相关实体
【发布时间】:2016-02-26 03:31:30
【问题描述】:

考虑以下实体

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 由 Entity Framework 自动生成。

我正在使用 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 语句与 FOREIGN KEY 约束冲突。

错误的原因是Product 实体没有SupplierId,因为它是数据库生成的密钥。

那么如何在保存记录的同时将SupplierId 添加到Product 实体? 谁能帮我解决这个问题?

【问题讨论】:

    标签: c# entity-framework asp.net-web-api odata odata-v4


    【解决方案1】:

    好的,感谢您的澄清。假设您使用的是 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();
    

    【讨论】:

    • 是的,我同意,问题是错误的。现在我已经编辑了这个问题。在您的示例中,您正在这样做:s.ProductId = p.ProductId; 据我所知,p.ProductId 仍然没有价值,对吧?那么这个任务是如何工作的呢?它将从数据库序列中获得价值,对吗?能解释一下吗?
    • 我已经修改了代码并运行了解决方案,但我仍然遇到同样的错误。 > INSERT 语句与 FOREIGN KEY 约束“FK_dbo.Product_dbo.Supplier_SupplierId”冲突。数据库“DBContext”、表“dbo.Supplier”、“Id”列中发生冲突。该语句已终止。我调试并注意到供应商是在数据库中创建的,但不是产品。
    【解决方案2】:

    使用 OData V4,您可以尝试深度插入方法。 Deep Insert 允许在一个请求中创建相关实体树。 http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793718

    【讨论】:

    • 这正是我所需要的。但是如何在 DataService 客户端或 Odata v4 客户端中实现这一点
    【解决方案3】:

    我认为 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);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多