C# DTO如何在实体框架内部绑定

C# DTO如何在实体框架内部绑定,c#,entity-framework-core,C#,Entity Framework Core,实际上,我正在尝试使用DTO(POCO类)为CRUD操作创建一个通用库 但在API中,我们有许多复杂的请求和响应。因此,我想创建自己的格式来执行CRUD操作。所以我试图理解DTO是如何在实体框架中绑定的,这样我就可以创建一个逻辑,这样我就可以将任何DTO直接保存到数据库中 比如说 当我们使用实体框架在数据库中保存任何内容时,我们只需像这样传递完整的DTO对象 context.Add(author); context.SaveChanges(); 在我的例子中,author DTO要有更多不用于

实际上,我正在尝试使用DTO(POCO类)为CRUD操作创建一个通用库

但在API中,我们有许多复杂的请求和响应。因此,我想创建自己的格式来执行CRUD操作。所以我试图理解DTO是如何在实体框架中绑定的,这样我就可以创建一个逻辑,这样我就可以将任何DTO直接保存到数据库中

比如说

当我们使用实体框架在数据库中保存任何内容时,我们只需像这样传递完整的DTO对象

context.Add(author);
context.SaveChanges();
在我的例子中,author DTO要有更多不用于保存的属性,在我发送响应时会使用额外属性。因此,这个额外属性抛出错误表示,当我使用此代码保存时,这个额外属性与列不匹配

context.Add(作者);
SaveChanges();
因此,简单地说,我想创建一个通用方法,在这个方法中,我可以在DTO中发送尽可能多的属性,但它只保存那些与数据库表匹配的属性

这里有完整的细节

(场景1) 假设我有一位作家

类作者
{
公共int AuthorId{get;set;}
public int AuthorName{get;set;}
公共int作者{get;set;}
}
有一个包含列的表

AuthorId
AuthorName
AuthorAge
当我使用

context.Add(作者);
SaveChanges();
它工作得很好

(场景2)

类作者
{
公共int AuthorId{get;set;}
public int AuthorName{get;set;}
公共int作者{get;set;}
}
教材:作者
{
public int BookId{get;set;}
public int BookName{get;set;}
}
和带有列的表

BookId ,
BookName ,
AuthorId 
在这种情况下,当我使用

context.Add(书籍);
SaveChanges();
它将给出错误

通过对AuthorName执行[NotMapped],AuthorAge将不会在场景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;}}
   }
公共类作者
{
公共int AuthorId{get;set;}
公共字符串AuthorName{get;set;}
公共int作者{get;set;}
公共虚拟列表书{get;set;}
}
公共部分类书
{
public int BookId{get;set;}
公共字符串BookName{get;set;}
公共int AuthorId{get;set;}
公共虚拟作者{get;set;}
}
公共部分类书
{
公共字符串AuthorName{get{返回Author.AuthorName;}}
public int AuthorAge{get{返回Author.AuthorAge;}}
}

在这种情况下继承是错误的。当继承某些东西时,你应该问自己:“X也是Y吗?”在本例中是“书是作者吗?”,其实不是。一本书有一个作者,所以我们需要一个对它的引用,而不是从作者那里继承

在普通课程中,我们只需这样做:

公共课堂教材
{
公共作者{get;set;}
}
但因为这不是一个普通的类,而是实体框架的模型,所以我们需要这样做:

公共课堂教材
{
public int BookId{get;set;}
公共字符串BookName{get;set;}
公共int AuthorId{get;set;}
公共虚拟作者{get;set;}
}
像这样保持你的作者类

公共类作者
{
公共int AuthorId{get;set;}
public int AuthorName{get;set;}
公共int作者{get;set;}
}
在数据库上,这将创建两个表:

Author Table:
|AuthorId|AuthorName|AuthorAge|
|--------|----------|---------|
|...     |...       |...      |
|--------|----------|---------|

Book Table:
|BookId|AuthorId|BookName|
|------|--------|--------|
|...   |...     |...     |
|------|--------|--------|
其中,Book表中的
AuthorId
是Author表的外键
AuthorId

现在,通过执行
book.Author.AuthorName
,您可以轻松访问任何书籍的作者信息


请注意,这些表都是示例,它们的实际名称和列的名称不是EF将在您的数据库中生成的名称。它们仅用于演示目的

我认为您缺少了层,您的
DTO
只是在方法/命令/队列之间流动的
DTO
(数据传输对象),您应该拥有
DbModel
,它们是
数据库上下文中的属性的
部分


public partial class BookStoreContext : DbContext
{
  public BookStoreContext(DbContextOptions<BookStoreContext> options) : base(options)
  {
  }

  public DbSet<Author> Authors { get; set; }
  public DbSet<Book> Book { get; set; }
}

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; }
}

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;}
}

神奇之处在于这样一个库,它将帮助您将DTO映射到
模型

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)));
...


var book = mapper.Map<BookTo, Book>(bookTo);
context.Add(books);
context.SaveChanges();

...

希望这对你有帮助:)


这很简单。只需将
[NotMapped]
属性添加到您不想保存在数据库中的每个属性,以便该属性仅在某些时候使用?您能否展开您的问题,并添加一个DTO类的示例,该类具有仅在某些时候使用的属性?此外,是什么阻止您将属性保存到数据库中,使其仅为NULL(在数据库中不是必需的)?
classbook:Author
是一种无意义的关系。书不是作者。一本书有一个或多个作者。在第二个场景中,您实际保存的是Author类的实例还是book类的实例?而且,这里的继承是错误的。一本书不是作者,因此不应该从作者那里继承。相反,一本书有一个作者(有时有多个作者,但我暂时不考虑),所以应该有一个参考文献。除了格式非常糟糕之外,你的答案不会试图解释任何东西。此外,如果Book将Author作为属性引用,则不应将Author的属性添加到Book中,因为这只是多余的
类Book:Author
表明他希望从Book级别访问Author属性。这就是我所做的。那么为什么要向Book类添加冗余属性,而不是只执行
Book.Author.AuthorName
?反复键入
Book.Author.AuthorName
,当有5行代码时,我不必每次都键入额外的作者。这