• ABP文档


    文档目录

    本节内容:

    ABP可使用任何ORM框架,它已经内置了EntityFrame(以下简称EF),这个文档将解释如何在ABP里使用EF,我们假设你对EF已经有初步的了解。

    Nuget 包

    在ABP里使用EF的Nuget包是Abp.EntityFramework,你应该把它加入到你的应用里,最好在你项目里单独建立一个EF程序集(dll),然后依赖该于这个包。

    DbContext

    如你所知,要使用EF,应当先为你的应用定义一个DbContext,如下所示:

    public class SimpleTaskSystemDbContext : AbpDbContext
    {
        public virtual IDbSet<Person> People { get; set; }
        public virtual IDbSet<Task> Tasks { get; set; }
    
        public SimpleTaskSystemDbContext()
            : base("MyConnectionStringName")
        {
    
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            modelBuilder.Entity<Person>().ToTable("StsPeople");
            modelBuilder.Entity<Task>().ToTable("StsTasks").HasOptional(t => t.AssignedPerson);
        }
    }

    除了从AbpDbContext继承(不是DbContext)外,其它的与普通的DbContext没分别,AbpDbContext有多个重载,你可以按需要使用它们。

    EF可以以一种约定的方式映射类到数据库表,你甚至不用进行配置,除非你自定义了一些东西,在这个例子里,我们映射实体到不同的表,按默认Task实体映射到Tasks表,但我们把它修改成StsTasks表,也可以用数据注解特性代替配置。我更喜欢使用流畅的配置,你可按喜好选择。

    仓储

    仓储用来抽象来自更高层的数据访问,查看仓储文档获取更多。

    默认仓储

    Abp.EntityFramework为所有定义在你的DbContext里的实体,实现了默认的仓储,你不用创建仓储类,就可以直接使用预定义的仓储方法,例如:

    public class PersonAppService : IPersonAppService
    {
        private readonly IRepository<Person> _personRepository;
    
        public PersonAppService(IRepository<Person> personRepository)
        {
            _personRepository = personRepository;
        }
    
        public void CreatePerson(CreatePersonInput input)
        {        
            person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };
    
            _personRepository.Insert(person);
        }
    } 

    PersonAppService构造器注入了IRepository<Person>,然后使用Insert方法,以这种方式,你可以简单的注入IRepository<TEntity>(或IRepository<TEntity,TPrimaryKey>),然后使用预定义方法,查看仓储文档了解所有预定义方法。

    自定义仓储

    如果标准的仓储方法不能满足,你可以为你的实体创建自定义的仓储类。

    特定的仓储基类

    ABP提供了一个基类EfRepositoryBase,可以很容易地实现仓储。为实现IRepository接口,你的仓储可以直接继承该类,但最好是扩展EfRepositoryBase类,你可以在你的仓储里添加共享/通用的方法。一个SimpleTaskSystem应用的所有仓储的基类示例:

    //Base class for all repositories in my application
    public class SimpleTaskSystemRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>
        where TEntity : class, IEntity<TPrimaryKey>
    {
        public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
            : base(dbContextProvider)
        {
        }
    
        //add common methods for all repositories
    }
    
    //A shortcut for entities those have integer Id
    public class SimpleTaskSystemRepositoryBase<TEntity> : SimpleTaskSystemRepositoryBase<TEntity, int>
        where TEntity : class, IEntity<int>
    {
        public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
            : base(dbContextProvider)
        {
        }
    
        //do not add any method here, add to the class above (because this class inherits it)

    注意:我们从 EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>继承,这表明在我们仓储里,ABP使用SimpleTaskSystemDbContext 。

    自定义仓储示例

    为实现一个自定义仓储,可以直接继承你应用里特定的仓储基类(如我们上面创建的)。

    假设我们有一个Task实体,它可以分配给一个Person(实体),并且一个Task有一个State(new,assigned,completed...),我们需要编写一个自定义方法,通过一些条件和预先获取的AssisgnedPerson属性使用一条数据库查询,获取Tasks列表,示例代码如下:

    public interface ITaskRepository : IRepository<Task, long>
    {
        List<Task> GetAllWithPeople(int? assignedPersonId, TaskState? state);
    }
    
    public class TaskRepository : SimpleTaskSystemRepositoryBase<Task, long>, ITaskRepository
    {
        public TaskRepository(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
            : base(dbContextProvider)
        {
        }
    
        public List<Task> GetAllWithPeople(int? assignedPersonId, TaskState? state)
        {
            var query = GetAll();
    
            if (assignedPersonId.HasValue)
            {
                query = query.Where(task => task.AssignedPerson.Id == assignedPersonId.Value);
            }
    
            if (state.HasValue)
            {
                query = query.Where(task => task.State == state);
            }
    
            return query
                .OrderByDescending(task => task.CreationTime)
                .Include(task => task.AssignedPerson)
                .ToList();
        }
    }

    我们首先定义ITaskRepository,然后实现它,GetAll()返回IQueryable<Task>,然后我们使用给定的参数添加一些Where过滤,最后我们可以调用ToList()来获取Tasks列表。

    你可以在你的仓储方法里使用Context对象,从而直接使用EF的API。

    注意:在领域/核心层定义自定义的仓储接口,在EF所在项目层里实现接口,因此你可以在任何项目里注入这个接口而不用引用EF。

    仓储最佳实践

    • 尽可能使用默认仓储,即使你有一个某实体的自定义的仓储,你也可以使用默认仓储(当使用标准的仓储方法)。
    • 为你的应用里的自定义仓储创建一个仓储基类,如上面那样定义。
    • 在领域层定义你自定义仓储的接口(启动模板里的.Core项目),在EF所在项目里定义自定义仓储的类。

    kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration 

  • 相关阅读:
    Serialization and deserialization are bottlenecks in parallel and distributed computing, especially in machine learning applications with large objects and large quantities of data.
    Introduction to the Standard Directory Layout
    import 原理 及 导入 自定义、第三方 包
    403 'Forbidden'
    https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
    These interactions can be expressed as complicated, large scale graphs. Mining data requires a distributed data processing engine
    mysqldump --flush-logs
    mysql dump 参数
    mysql dump 参数
    如果是在有master上开启了该参数,记得在slave端也要开启这个参数(salve需要stop后再重新start),否则在master上创建函数会导致replaction中断。
  • 原文地址:https://www.cnblogs.com/kid1412/p/6026034.html
Copyright © 2020-2023  润新知