在Entity Framework中保存数据+关系数据的最佳/最简单方法

问题描述 投票:1回答:3

在Entity Framework中考虑这个简单的一对多关系。一个组织拥有许多产品。

public class Product
{
    public int Id { get; set; }

    [StringLength(20)]
    public string Title { get; set; }

    [StringLength(300)]
    public string Description { get; set; }

    public float Price { get; set; }
    public DateTime CreationDate { get; set; }

    public virtual Organisation Organisation { get; set; }

    public Product()
    {
        CreationDate = DateTime.Now;
    }
}

public class Organisation
{
    public int Id { get; set; }

    [StringLength(20)]
    public string Title { get; set; }

    [StringLength(400)]
    public string Description { get; set; }

    public DateTime CreationDate { get; set; }

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

如果我有一个(post)api调用,接受正文中的原始数据(json格式的文本),这允许用户在同一个调用中创建一个组织和任意数量的产品。如何使用Entity Framework将这些数据正确保存到数据库中?

据我所知,我正在使用延迟加载(由于在模型中设置关系时使用虚拟关键字),所以不应该自动处理关系?如果我保存数据,如下面的控制器操作(调用后的控制器操作)。它会起作用吗?如果没有,那么使用Entity Framework保存包含另一个模型列表的模型的适当/最佳实践方法是什么。

public IHttpActionResult CreateOrganisation(Organisation org)
{           
    db.Organisations.Add(org);
    db.SaveChanges();
    return Ok(org);
}

真的似乎无法在文档中找到这个?

c# .net entity-framework asp.net-web-api2
3个回答
0
投票

好吧,我没有时间尝试它,但是看看你的代码,我看到有一些建议,如果你正在寻找最好的做法,我可能会指向你,即使这些也没有回答你的问题:

  1. 使用异步任务模式创建Web API控制器以避免死锁: public async Task<IHttpActionResult> CreateOrganisation(Organisation org)
  2. 将调用方法(您的ef的业务逻辑)设置为与上面相同的模式。在这种情况下,请使用SaveChangesAsync()方法。在控制器中调用任何方法作为上述示例时,不要忘记使用关键字await。
  3. 利用关注点的分离。从控制器类中应用BL。
  4. 应用SOLID原则。反转的依赖性,字母D,例如使用Microsfot Unity IOC容器,使用抽象类,接口使类松散耦合,因此应用注入的依赖性。
  5. 尝试使用视图模型来验证模型,而不是EF数据第一模型或代码优先模型生成的域类。
  6. 最后但并非最不重要的,强烈打字!!!!

我希望这些建议可以帮到你。


0
投票

既然你要求“最佳实践”,我会告诉你一个技术,当EF对象图的处理有点时,我必须回过头来处理这个技术,我们会说“iffy”吗?

首先,每个物理存储的实体具有相应的DTO对象。 ViewModel(MVVM-speak)的一部分是该View的必要DTO对象。添加了其他字段以便为每个实体传达State(UI所做的)。它看起来像这样:

public class ProductDTO {
    // Same fields, mostly
    public string Action { get; set; }    // A, C, D
}

public class OrganizationDTO {
    // Same fields except children
    public ICollection<ProductDTO> Products { get; set; }
    public string Action { get; set; }
}

基于顶级DTO,POST,PUT或DELETE(A,C,D)中的非空白动作。 UI设置每个实体的状态。对孩子的修改被视为对父母的“改变”。

然后在后端的CRUD方法中...不可否认,这是大锤的方法。

public class OrganizationRepository : whatever interfaces {
    public void Add (OrganizationDTO newOrg) {
        if (newOrg.Action != "A")    // Why are you here?
           throw an exception (bad request)

        context.Organizations.Add(Map DTO to entity here);
        foreach (var item in newOrg.Products) {
            switch (item.Action)
            case "A":
                ProductRepository.Add(item,newOrg.Id);
                break;
            case "C":
                ProductRepository.Update(item,newOrg.Id);
                break;
            case "D":
                ProductRepository.Delete(item);
                break;
        }
        context.SaveChanges();
    }

    public void Update (OrganizationDTO oldOrg) {
        if (newOrg.Action != "C")    // Why are you here?
           throw an exception (bad request)

        context.Organizations.Attach(Map DTO to entity here);
        foreach (var item in newOrg.Products) {
            switch (item.Action)
            case "A":
                ProductRepository.Add(item,newOrg.Id);
                break;
            case "C":
                ProductRepository.Update(item,newOrg.Id);
                break;
            case "D":
                ProductRepository.Delete(item);
                break;
        }
        context.SaveChanges();
        return Ok();
    }
}

这不是工作/测试代码。只是粗糙的袖口。必须在添加时处理FK。添加您的映射技术。处理碰撞,尝试/捕捉等


-1
投票

我认为你的代码不能自我解释。 如果我是一个开发人员,看看你在这里发布的方法,我根本不明白我有可能发送嵌套数据。

我会对对象“org”的Products集合进行迭代,然后将它们添加到EF集合中,然后将组织添加到自己的集合中。

然后,显然,SaveChanges()。

这可以清楚地区分接受嵌套对象的这种方法,以及另一种不支持嵌套对象的方法,并简单地保存我的新空组织。

© www.soinside.com 2019 - 2024. All rights reserved.