gpt4 book ai didi

C# Entity Framework : Data validation between add to context and saveChanges()

转载 作者:太空狗 更新时间:2023-10-30 01:02:10 26 4
gpt4 key购买 nike

我有一个使用 C# Entity Framework 的简单场景。我有一个实体帖子:

public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

在我的 PostManager 中我有这些方法:

public int AddPost(string name, string description)
{
var post = new Post() { Name = name, Description = description };

using (var db = new DbContext())
{
var res = db.Posts.Add(post);
res.Validate();
db.SaveChanges();
return res.Id;
}
}

public void UpdatePost(int postId, string newName, string newDescription)
{
using (var db = new DbContext())
{
var data = (from post in db.Posts.AsEnumerable()
where post.Id == postId
select post).FirstOrDefault();

data.Name = newName;
data.Description = newDescription;
data.Validate();
db.SaveChanges();
}
}

validate()方法引用类:

public static class Validator
{
public static void Validate(this Post post)
{
if ( // some control)
throw new someException();
}

我在 savechanges() 之前但在将对象添加到上下文之后调用了验证方法。在这个简单的场景中验证数据的最佳实践是什么?最好验证参数吗?如果在将对象添加到上下文后验证方法抛出异常,对象 post 会发生什么情况?

更新:

我必须根据数据验证错误抛出一组自定义异常。

最佳答案

我强烈建议您(如果可能的话)修改您的实体,以便 setter 是私有(private)的(不用担心,EF 仍然可以在代理创建时设置它们),将默认构造函数标记为 protected (EF 仍然可以做延迟加载/代理创建),并使唯一可用的公共(public)构造函数检查参数。

这有几个好处:

  • 您限制实体状态可以更改的地方的数量,从而减少重复
  • 你保护你类(class)的不变量。通过强制通过构造函数创建实体,您可以确保实体的对象不可能以无效或未知状态存在。
  • 您获得更高的凝聚力。通过将数据约束置于更接近数据本身的位置,可以更轻松地理解和推理您的类。
  • 您的代码在更高程度上成为自文档。人们永远不必怀疑“如果我在此 int 属性上设置负值是否可以?”如果一开始就不可能做到。
  • 关注点分离。您的经理不应该知道如何验证实体,这只会导致高耦合。我见过许多经理成长为无法维护的怪物,因为他们什么都做。持久化、加载、验证、错误处理、转换、映射等。这基本上是 SOLID OOP 的对立面。

我知道现在非常流行将所有“模型”制作成带有 getter 和 setter 的愚蠢属性包,并且只有一个默认构造函数,因为(糟糕的)ORM 迫使我们这样做,但现在不再是这样了,这个 imo 有很多问题。

代码示例:

public class Post
{
protected Post() // this constructor is only for EF proxy creation
{
}

public Post(string name, string description)
{
if (/* validation check, inline or delegate */)
throw new ArgumentException();

Name = name;
Description = description;
}

public int Id { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
}

然后您的 PostManager 代码变得微不足道:

using (var db = new DbContext())
{
var post = new Post(name, description); // possibly try-catch here
db.Posts.Add(post);
db.SaveChanges();
return post.Id;
}

如果创建/验证逻辑极其复杂,则此模式非常适合重构为负责创建的工厂。

我还要指出,将数据封装在公开最小状态更改 API 的实体中会导致类的隔离测试更容易几个数量级,如果您完全关心这类事情的话。

关于C# Entity Framework : Data validation between add to context and saveChanges(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34924687/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com