实际上,我正在尝试使用DTO(POCO类)为CRUD操作创建一个通用库。
但是在API中,我们有许多复杂的请求和响应。所以我想创建自己的格式来执行CRUD操作。因此,我试图了解DTO在Entity Framework中是如何绑定的,以便我可以以可以将任何DTO直接保存在数据库中的方式创建逻辑。
例如
当我们使用实体框架将任何内容保存在数据库中时,我们只是像这样传递完整的DTO对象。
context.Add(author);
context.SaveChanges();
在我的情况下,作者DTO有更多不用于保存目的的属性,当我发送响应时会使用额外的属性。因此,此额外的属性抛出错误表示当我以此保存时,此额外的属性与列不匹配代码
context.Add(author);
context.SaveChanges();
因此,我想简单地创建一个通用方法,在该方法中我可以在DTO中发送尽可能多的属性,但是它只保存那些与数据库表匹配的属性。
此处有完整的详细信息
(场景1) 假设我有DTO作者
class Author
{
public int AuthorId {get;set;}
public int AuthorName {get;set;}
public int AuthorAge {get;set;}
}
有一个带有列的表
AuthorId
AuthorName
AuthorAge
当我使用保存时
context.Add(author);
context.SaveChanges();
工作正常。
(场景2)
class Author
{
public int AuthorId {get;set;}
public int AuthorName {get;set;}
public int AuthorAge {get;set;}
}
class Book : Author
{
public int BookId {get;set;}
public int BookName {get;set;}
}
还有带有列的表
BookId ,
BookName ,
AuthorId
在这种情况下,我使用来保存数据
context.Add(books);
context.SaveChanges();
它将给出错误。
通过对AuthorName执行[NotMapped],AuthorAge将不会在场景1中保存记录。
我希望你明白我想说的话。
答案 0 :(得分:0)
在这种情况下,继承是错误的。从某事物继承时,您应该问自己:“ X也是Y吗?”在这种情况下,“是作者吗?”,不是。一本书有一个作者,因此我们需要从它那里引用而不是从作者那里继承。
在普通课程中,我们只会这样做:
public class Book
{
public Author Author {get; set;}
}
但是因为这不是普通的类,所以它是实体框架的模型,我们需要这样做:
public class Book
{
public int BookId {get; set;}
public string BookName {get; set;}
public int AuthorId {get; set;}
public virtual Author Author {get; set;}
}
像这样保持您的Author类
public class Author
{
public int AuthorId {get; set;}
public int AuthorName {get; set;}
public int AuthorAge {get; set;}
}
在数据库上,这将创建两个表:
Author Table:
|AuthorId|AuthorName|AuthorAge|
|--------|----------|---------|
|... |... |... |
|--------|----------|---------|
Book Table:
|BookId|AuthorId|BookName|
|------|--------|--------|
|... |... |... |
|------|--------|--------|
“书”表中的AuthorId
是作者表AuthorId
的外键
您现在可以通过执行book.Author.AuthorName
轻松访问任何书籍的作者信息。
P.S请注意,这些表只是示例,它们的实际名称和列的名称不是EF在数据库中生成的。它们只是出于示范目的
答案 1 :(得分:0)
我认为您缺少图层,您的DTO
仅是DTO
(数据传输对象),它们将在方法/命令/队列之间流动,因此您应该拥有DbModel
partial
类是您的DbContext
DbContext
public partial class BookStoreContext : DbContext
{
public BookStoreContext(DbContextOptions<BookStoreContext> options) : base(options)
{
}
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Book { get; set; }
}
DbModels
public partial class Author
{
public int Id {get;set;}
public string Name {get;set;}
public int Age {get;set;}
public virtual List<Book> Books {get;set;}
}
public partial class Book
{
public int Id {get;set;}
public string Name {get;set;}
public int AuthorId {get;set;}
public virtual Author Author {get;set;}
}
DTO
class AuthorTo
{
public int AuthorId {get;set;}
public int AuthorName {get;set;}
public int AuthorAge {get;set;}
}
class BookTo : AuthorTo
{
public int BookId {get;set;}
public int BookName {get;set;}
}
魔术存在于AutoMapper
之类的库中,这将帮助您将DTO映射到Model
var configuration = new MapperConfiguration(cfg =>
cfg.CreateMap<BookTo, Book>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.BookId))
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.BookName))
.ForMember(dest => dest.AuthorId, opt => opt.MapFrom(src => src.AuthorId)));
然后您可以Map
将DTO
变成Model
...
var book = mapper.Map<BookTo, Book>(bookTo);
context.Add(books);
context.SaveChanges();
...
希望这对您有所帮助:)
答案 2 :(得分:-1)
这就是我编写课程的方式
public class Author
{
public int AuthorId {get;set;}
public string AuthorName {get;set;}
public int AuthorAge {get;set;}
public virtual List<Book> Books {get;set;}
}
public partial class Book
{
public int BookId {get;set;}
public string BookName {get;set;}
public int AuthorId {get;set;}
public virtual Author Author {get;set;}
}
public partial class Book
{
public string AuthorName {get{return Author.AuthorName;}}
public int AuthorAge {get{return Author.AuthorAge;}}
}