gpt4 book ai didi

asp.net-mvc - MVC 中具有存储库/DTO 模式的实体的部分更新(为 API 做准备)

转载 作者:行者123 更新时间:2023-12-04 12:18:44 25 4
gpt4 key购买 nike

我已经构建了我的域模型层、我的存储库层,现在我正在处理我的 DTO 层以供 webApi 项目使用。我正在实现更新服务方法,我想知道部分更新。这是我的 DTO 类(class):

public class FullPersonDto
{
public FullPersonDto()
{
Friends = new List<Person>();
}

public FullPersonDto(Person person)
{
PersonId = person.PersonId;
DateCreated = person.DateCreated;
Details = person.Details;
Friends = new List<Person>();
foreach (Person friend in person.Friends)
{
Friends.Add(new PersonDto(friend));
}
}

[Key]
public int PersonId { get; set; }

[Required]
public virtual DateTime DateCreated { get; set; }

public virtual string Details { get; set; }

public List<Person> Friends { get; set; }

public Person ToEntity()
{
var person = new Person
{
PersonId = PersonId,
DateCreated = (DateTime) DateCreated,
Details = Details,
Friends = new List<Person>()
};
foreach (PersonDto friend in Friends)
{
person.Friends.Add(friend.ToEntity());
}
return person;
}
}

这是我的存储库中的更新方法:
public Person UpdatePerson(Person person)
{
var entry = _db.Entry(person);
if (entry.State == EntityState.Detached)
{
var dbSet = _db.Set<Person>();
Person attachedPerson = dbSet.Find(person.PersonId);
if (attachedPerson != null)
{
var attachedEntry = _db.Entry(attachedPerson);
attachedEntry.CurrentValues.SetValues(person); // what if values are null, like ID, or DateCreated?
}
else
{
entry.State = EntityState.Modified;
}

}
SaveChanges();
return person;
}

我的问题是:如果我只需要通过我的 webAPI 更新一个人的详细信息怎么办?是构造一个完整的 PersonDto 并使用 SetValues 更新整个对象的约定,还是有什么方法可以指定我只想要更新一个字段,这样我就不必通过网络发送大量数据(即我真的不需要)?

如果可以进行部分更新,那么何时更新整个实体最好?即使我必须更新 5/7 属性,它也需要我发送 2/7 的旧数据以重新写入,以便 SetValues 不会将空值从我的 DTO 写入我的字段。

这里的任何帮助都会很棒......对这些东西完全陌生,并尝试正确学习所有内容。谢谢你。

最佳答案

我采用了类似的方法进行优化,并且在附加时遇到了同样的空值问题(不仅仅是空值, bool 值也会有问题)。这就是我想出的:

    public static void Update<T>(this DbContext context, IDTO dto)
where T : class, IEntity
{
T TEntity = context.Set<T>().Local.FirstOrDefault(x => x.Id == dto.Id);
if (TEntity == null)
{
TEntity = context.Set<T>().Create();
TEntity.Id = dto.Id;
context.Set<T>().Attach(TEntity);
}
context.Entry(TEntity).CurrentValues.SetValues(dto);
var attribute = dto.GetAttribute<EnsureUpdatedAttribute>();
if (attribute != null)
{
foreach (var property in attribute.Properties)
context.Entry(TEntity).Property(property).IsModified = true;
}
}

那是 DbContext 的扩展方法。下面是接口(interface) IDTO 和 IEntity:
public interface IDTO
{
int Id { get; set; }
}

public interface IEntity
{
int Id { get; set; }

Nullable<DateTime> Modified { get; set; }
Nullable<DateTime> Created { get; set; }
}

我正在使用我的自定义 EnsureUpdatedAttribute 来注释应始终更新哪些属性(以处理未跟踪的空值/默认值):
public class EnsureUpdatedAttribute : Attribute
{
public IEnumerable<string> Properties { get; private set; }

public EnsureUpdatedAttribute(params string[] properties)
{
Properties = properties.AsEnumerable();
}
}

这是一个使用示例:
public class Sample : IEntity
{
public int Id { get; set; }

public string Name { get; set; }

public bool Active { get; set; }

public Nullable<DateTime> Modified { get; set; }
public Nullable<DateTime> Created { get; set; }
}


[EnsureUpdated("Active")] /// requirement for entity framework change tracking, read about stub entities
public class SampleDTO : IDTO
{
public int Id { get; set; }

[Required]
public string Name { get; set; }

[JsonIgnore] /// How to exclude property from going on the wire / ignored for serialization
public bool Active { get; set; }
}

[HttpPost]
public HttpResponseMessage SaveSample(SampleDTO dto)
{
dto.Active = true;
_ctx.AddModel<Sample>(dto);
_ctx.SaveChanges();
return NoContent();
}

return NoContent() 只是返回 204 (NoContent) 的扩展。

希望这可以帮助。

关于asp.net-mvc - MVC 中具有存储库/DTO 模式的实体的部分更新(为 API 做准备),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15329436/

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