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

时间:2019-07-15 06:27:24

标签: c# entity-framework-core

实际上,我正在尝试使用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中保存记录。

我希望你明白我想说的话。

3 个答案:

答案 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)));

然后您可以MapDTO变成Model

...


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

...

希望这对您有所帮助:)

AutoMapper docs

How to get started with AutoMapper and ASP.NET Core 2

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