EF usage with ABP
Learning Note About the useage of ABP
-
useage of EF code first.
- firstly, follow these steps to complete a db and model sync:
add-migration -name 'xxx'
and thenupdate-database -verbose
, last publish the web project. - Consider these scenario, db already ready, we generate model from EF-VS-help(like, add dataitem project), we should run these commands sequence:
add-migration -name 'xxx' -ignorechanges
and thenupdate-database -verbose
, last publish the web project. - Keep in mind that, every add-migration should be matched with update-database, otherwise, we will meet with the DBContext initialize error.
- firstly, follow these steps to complete a db and model sync:
-
some suggestions about the model structors.
- create a customized baseClass
which inherited from Entity . - all models should inherited from baseClass
. - code snippet here:
- Base class definition
- create a customized baseClass
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Domain.Entities;
using System.Data.Entity.ModelConfiguration;
namespace Agency
{
public class AgencyEntityBase<TEntity,TPrimaryKey>:Entity<TPrimaryKey> where TEntity: class, new()
{
}
public class AgencyEntityBase<TEntity>:AgencyEntityBase<TEntity,int>where TEntity : class, new()
{
}
}
- each Entity Definition
namespace Agency
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
using Abp.Domain.Entities;
using System.Data.Entity.ModelConfiguration;
public partial class ApplicationUser:Entity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public ApplicationUser()
{
ApplicationUsers1 = new HashSet<ApplicationUser>();
UserRelationships = new HashSet<UserRelationship>();
}
public string NetworkUserName { get; set; }
public string CRMUserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreateDate { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public string Email { get; set; }
[StringLength(20)]
public string PhoneCountryCode { get; set; }
[StringLength(20)]
public string FaxCountryCode { get; set; }
public int? TeamLeaderId { get; set; }
public string LastIP { get; set; }
public DateTime? LastActivityDate { get; set; }
public int? StatusId { get; set; }
public int? CRMUserId { get; set; }
public virtual ApplicationUserStatus ApplicationUserStatus { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ApplicationUser> ApplicationUsers1 { get; set; }
public virtual ApplicationUser ApplicationUser1 { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<UserRelationship> UserRelationships { get; set; }
public static ApplicationUserModelMapper CreateMapper()
{
return new ApplicationUserModelMapper();
}
}
public class ApplicationUserModelMapper : EntityTypeConfiguration<ApplicationUser>
{
public ApplicationUserModelMapper()
{
this.Property(e => e.PhoneCountryCode).IsUnicode(false);
this.Property(e => e.FaxCountryCode).IsUnicode(false);
this.HasMany(e => e.ApplicationUsers1)
.WithOptional(e => e.ApplicationUser1)
.HasForeignKey(e => e.TeamLeaderId);
this.HasMany(e => e.UserRelationships)
.WithRequired(e => e.ApplicationUser)
.HasForeignKey(e => e.UserId)
.WillCascadeOnDelete(false);
}
}
}
- DbContext definition
using System.Data.Common;
using Abp.Zero.EntityFramework;
using Agency.Authorization.Roles;
using Agency.Authorization.Users;
using Agency.MultiTenancy;
using Agency;
using System.Data.Entity;
namespace Agency.EntityFramework
{
public class AgencyDbContext : AbpZeroDbContext<Tenant, Role, User>
{
//TODO: Define an IDbSet for your Entities...
public virtual DbSet<CreditAgreement> CreditAgreements { get; set; }
public virtual DbSet<Facility> Facilities { get; set; }
public virtual DbSet<ReportParameterRelationship> ReportParameterRelationships { get; set; }
public virtual DbSet<ReportParameter> ReportParameters { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<ApplicationUser> ApplicationUsers { get; set; }
public virtual DbSet<ApplicationUserStatus> ApplicationUserStatus { get; set; }
public virtual DbSet<UserGroupInfo> UserGroupInfoes { get; set; }
public virtual DbSet<UserRelationship> UserRelationships { get; set; }
/* NOTE:
* Setting "Default" to base class helps us when working migration commands on Package Manager Console.
* But it may cause problems when working Migrate.exe of EF. If you will apply migrations on command line, do not
* pass connection string name to base classes. ABP works either way.
*/
public AgencyDbContext()
: base("Default")
{
}
/* NOTE:
* This constructor is used by ABP to pass connection string defined in AgencyDataModule.PreInitialize.
* Notice that, actually you will not directly create an instance of AgencyDbContext since ABP automatically handles it.
*/
public AgencyDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
//This constructor is used in tests
public AgencyDbContext(DbConnection existingConnection)
: base(existingConnection, false)
{
}
public AgencyDbContext(DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(ApplicationUser.CreateMapper());
modelBuilder.Configurations.Add(Agency.ApplicationUserStatus.CreateMapper());
modelBuilder.Configurations.Add(UserGroupInfo.CreateMapper());
base.OnModelCreating(modelBuilder);
}
}
}