diff --git a/src/AbpDesk/AbpDesk.Application.Contracts/AbpDesk/Tickets/Dtos/TicketDto.cs b/src/AbpDesk/AbpDesk.Application.Contracts/AbpDesk/Tickets/Dtos/TicketDto.cs index c4816fdde0..a0f3d3790e 100644 --- a/src/AbpDesk/AbpDesk.Application.Contracts/AbpDesk/Tickets/Dtos/TicketDto.cs +++ b/src/AbpDesk/AbpDesk.Application.Contracts/AbpDesk/Tickets/Dtos/TicketDto.cs @@ -7,5 +7,10 @@ namespace AbpDesk.Tickets.Dtos public string Title { get; set; } public string Body { get; set; } + + public override string ToString() + { + return $"{base.ToString()}, Title = {Title}, Body = {Body}"; + } } } \ No newline at end of file diff --git a/src/AbpDesk/AbpDesk.Application/AbpDesk/Tickets/TicketAppService.cs b/src/AbpDesk/AbpDesk.Application/AbpDesk/Tickets/TicketAppService.cs index 450202f35a..3b516576a0 100644 --- a/src/AbpDesk/AbpDesk.Application/AbpDesk/Tickets/TicketAppService.cs +++ b/src/AbpDesk/AbpDesk.Application/AbpDesk/Tickets/TicketAppService.cs @@ -1,17 +1,27 @@ -using System.Collections.Generic; +using System.Linq; using AbpDesk.Tickets.Dtos; using Volo.Abp.Application.Services.Dtos; +using Volo.Abp.Domain.Repositories; namespace AbpDesk.Tickets { public class TicketAppService : ITicketAppService { + private readonly IRepository _ticketRepository; + + public TicketAppService(IRepository ticketRepository) + { + _ticketRepository = ticketRepository; + } + public ListResultDto GetAll() { - return new ListResultDto(new List - { - new TicketDto {Id = 1, Title = "Ticket 1 Title", Body = "Ticket 1 Body" } - }); + var tickets = _ticketRepository + .GetAllList() + .Select(t => new TicketDto { Id = t.Id, Title = t.Title, Body = t.Body }) + .ToList(); + + return new ListResultDto(tickets); } } } diff --git a/src/AbpDesk/AbpDesk.ConsoleDemo/project.json b/src/AbpDesk/AbpDesk.ConsoleDemo/project.json index 2ec4f0ba24..cbc8231774 100644 --- a/src/AbpDesk/AbpDesk.ConsoleDemo/project.json +++ b/src/AbpDesk/AbpDesk.ConsoleDemo/project.json @@ -11,9 +11,17 @@ "Microsoft.NETCore.App": { "type": "platform", "version": "1.1.0" + }, + "Microsoft.EntityFrameworkCore.Tools": { + "type": "build", + "version": "1.1.0-preview4-final" } }, + "tools": { + "Microsoft.EntityFrameworkCore.Tools": "1.1.0-preview4-final" + }, + "frameworks": { "netcoreapp1.1": { "imports": "dnxcore50" diff --git a/src/AbpDesk/AbpDesk.Domain/AbpDesk/Tickets/Ticket.cs b/src/AbpDesk/AbpDesk.Domain/AbpDesk/Tickets/Ticket.cs index 0363d18475..fae10ee781 100644 --- a/src/AbpDesk/AbpDesk.Domain/AbpDesk/Tickets/Ticket.cs +++ b/src/AbpDesk/AbpDesk.Domain/AbpDesk/Tickets/Ticket.cs @@ -1,4 +1,7 @@ -using Volo.Abp.Domain.Entities; +using System.ComponentModel.DataAnnotations; +using JetBrains.Annotations; +using Volo; +using Volo.Abp.Domain.Entities; namespace AbpDesk.Tickets { @@ -8,8 +11,11 @@ namespace AbpDesk.Tickets public const int MaxBodyLength = 64 * 1024; //64K + [Required] + [MaxLength(MaxTitleLength)] public string Title { get; set; } + [MaxLength(MaxBodyLength)] public string Body { get; set; } private Ticket() @@ -17,8 +23,10 @@ namespace AbpDesk.Tickets } - public Ticket(string title, string body) + public Ticket([NotNull] string title, string body) { + Check.NotNull(title, nameof(title)); + Title = title; Body = body; } diff --git a/src/AbpDesk/AbpDesk.Domain/project.json b/src/AbpDesk/AbpDesk.Domain/project.json index 3ba528f0f6..321281f43a 100644 --- a/src/AbpDesk/AbpDesk.Domain/project.json +++ b/src/AbpDesk/AbpDesk.Domain/project.json @@ -3,6 +3,7 @@ "dependencies": { "NETStandard.Library": "1.6.1", + "System.ComponentModel.Annotations": "4.3.0", "Volo.Abp": "1.0.0-*" }, diff --git a/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDbContext.cs b/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDbContext.cs index 1a67bab778..b8c1fb030a 100644 --- a/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDbContext.cs +++ b/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDbContext.cs @@ -1,13 +1,15 @@ using AbpDesk.Tickets; using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; namespace AbpDesk.EntityFrameworkCore { - public class AbpDeskDbContext : DbContext + public class AbpDeskDbContext : AbpDbContext { - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + public AbpDeskDbContext(DbContextOptions options) + : base(options) { - optionsBuilder.UseSqlServer("Server=localhost;Database=AbpDesk;Trusted_Connection=True;"); + } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDomainModule.cs b/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDomainModule.cs deleted file mode 100644 index d92e47f4c9..0000000000 --- a/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskDomainModule.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; - -namespace AbpDesk.EntityFrameworkCore -{ - [DependsOn(typeof(AbpDeskDomainModule))] - public class AbpDeskEntityFrameworkCoreModule : AbpModule - { - public override void ConfigureServices(IServiceCollection services) - { - services.AddAssemblyOf(); - } - } -} diff --git a/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskEntityFrameworkCoreModule.cs b/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskEntityFrameworkCoreModule.cs new file mode 100644 index 0000000000..3d54bb4518 --- /dev/null +++ b/src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskEntityFrameworkCoreModule.cs @@ -0,0 +1,25 @@ +using AbpDesk.Tickets; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Modularity; +using Volo.Abp.Repositories.EntityFrameworkCore; + +namespace AbpDesk.EntityFrameworkCore +{ + [DependsOn(typeof(AbpDeskDomainModule))] + public class AbpDeskEntityFrameworkCoreModule : AbpModule + { + public override void ConfigureServices(IServiceCollection services) + { + services.AddAssemblyOf(); + + services.AddTransient, EfCoreRepository>(); + + services.AddDbContext(options => + { + options.UseSqlServer("Server=localhost;Database=AbpDesk;Trusted_Connection=True;"); + }); + } + } +} diff --git a/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/20161211123930_Ticket_Added_Data_Annotations.Designer.cs b/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/20161211123930_Ticket_Added_Data_Annotations.Designer.cs new file mode 100644 index 0000000000..95c11c5380 --- /dev/null +++ b/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/20161211123930_Ticket_Added_Data_Annotations.Designer.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using AbpDesk.EntityFrameworkCore; + +namespace AbpDesk.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(AbpDeskDbContext))] + [Migration("20161211123930_Ticket_Added_Data_Annotations")] + partial class Ticket_Added_Data_Annotations + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.0-rtm-22752") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("AbpDesk.Tickets.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Body") + .HasMaxLength(65536); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256); + + b.HasKey("Id"); + + b.ToTable("DskTickets"); + }); + } + } +} diff --git a/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/20161211123930_Ticket_Added_Data_Annotations.cs b/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/20161211123930_Ticket_Added_Data_Annotations.cs new file mode 100644 index 0000000000..6ef36d68ca --- /dev/null +++ b/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/20161211123930_Ticket_Added_Data_Annotations.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace AbpDesk.EntityFrameworkCore.Migrations +{ + public partial class Ticket_Added_Data_Annotations : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Title", + table: "DskTickets", + maxLength: 256, + nullable: false, + oldClrType: typeof(string), + oldNullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Title", + table: "DskTickets", + nullable: true, + oldClrType: typeof(string), + oldMaxLength: 256); + } + } +} diff --git a/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/AbpDeskDbContextModelSnapshot.cs b/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/AbpDeskDbContextModelSnapshot.cs index a8740f9595..178c4d100f 100644 --- a/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/AbpDeskDbContextModelSnapshot.cs +++ b/src/AbpDesk/AbpDesk.EntityFrameworkCore/Migrations/AbpDeskDbContextModelSnapshot.cs @@ -21,9 +21,12 @@ namespace AbpDesk.EntityFrameworkCore.Migrations b.Property("Id") .ValueGeneratedOnAdd(); - b.Property("Body"); + b.Property("Body") + .HasMaxLength(65536); - b.Property("Title"); + b.Property("Title") + .IsRequired() + .HasMaxLength(256); b.HasKey("Id"); diff --git a/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.xproj b/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.xproj index eae8272828..4d18ec7898 100644 --- a/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.xproj +++ b/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.xproj @@ -4,18 +4,17 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - a1ae63e9-0cf4-4afb-a584-65d826dea3cb - Volo.Abp.EntityFrameworkCore + + .\obj .\bin\ v4.6.1 - 2.0 - + \ No newline at end of file diff --git a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs new file mode 100644 index 0000000000..a918f93925 --- /dev/null +++ b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; + +namespace Volo.Abp.EntityFrameworkCore +{ + public class AbpDbContext : DbContext + where TDbContext : DbContext + { + public AbpDbContext(DbContextOptions options) + : base(options) + { + + } + } +} diff --git a/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Repositories/EntityFrameworkCore/EfCoreRepository.cs new file mode 100644 index 0000000000..4b42e628b8 --- /dev/null +++ b/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Repositories/EntityFrameworkCore/EfCoreRepository.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.EntityFrameworkCore; + +namespace Volo.Abp.Repositories.EntityFrameworkCore +{ + //TODO: Override async versions + + public class EfCoreRepository : RepositoryBase + where TDbContext : AbpDbContext + where TEntity : class, IEntity + { + protected virtual TDbContext DbContext { get; } + + protected virtual DbSet DbSet => DbContext.Set(); + + public EfCoreRepository(TDbContext dbContext) + { + DbContext = dbContext; + } + + public override List GetAllList() + { + return GetQueryable().ToList(); + } + + public override Task> GetAllListAsync() + { + return GetQueryable().ToListAsync(); + } + + public override TEntity Get(TPrimaryKey id) + { + var entity = FirstOrDefault(id); + if (entity == null) + { + throw new EntityNotFoundException(typeof(TEntity), id); + } + + return entity; + } + + public override TEntity FirstOrDefault(TPrimaryKey id) + { + return DbSet.Find(id); + } + + public override TEntity Insert(TEntity entity) + { + return DbSet.Add(entity).Entity; + } + + public override TEntity Update(TEntity entity) + { + return DbSet.Update(entity).Entity; + } + + public override void Delete(TEntity entity) + { + DbSet.Remove(entity); + } + + public override void Delete(TPrimaryKey id) + { + var entity = FirstOrDefault(id); + if (entity == null) + { + return; + } + + Delete(entity); + } + + public override int Count() + { + return GetQueryable().Count(); + } + + protected virtual IQueryable GetQueryable() + { + return DbSet; + } + } +} diff --git a/src/Volo.Abp/Volo/Abp/Domain/Entities/EntityNotFoundException.cs b/src/Volo.Abp/Volo/Abp/Domain/Entities/EntityNotFoundException.cs new file mode 100644 index 0000000000..762b86876c --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Domain/Entities/EntityNotFoundException.cs @@ -0,0 +1,78 @@ +using System; + +namespace Volo.Abp.Domain.Entities +{ + /// + /// This exception is thrown if an entity excepted to be found but not found. + /// + //[Serializable] + public class EntityNotFoundException : AbpException + { + /// + /// Type of the entity. + /// + public Type EntityType { get; set; } + + /// + /// Id of the Entity. + /// + public object Id { get; set; } + + /// + /// Creates a new object. + /// + public EntityNotFoundException() + { + + } + + ///// + ///// Creates a new object. + ///// + //public EntityNotFoundException(SerializationInfo serializationInfo, StreamingContext context) + // : base(serializationInfo, context) + //{ + + //} + + /// + /// Creates a new object. + /// + public EntityNotFoundException(Type entityType, object id) + : this(entityType, id, null) + { + + } + + /// + /// Creates a new object. + /// + public EntityNotFoundException(Type entityType, object id, Exception innerException) + : base($"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException) + { + EntityType = entityType; + Id = id; + } + + /// + /// Creates a new object. + /// + /// Exception message + public EntityNotFoundException(string message) + : base(message) + { + + } + + /// + /// Creates a new object. + /// + /// Exception message + /// Inner exception + public EntityNotFoundException(string message, Exception innerException) + : base(message, innerException) + { + + } + } +} diff --git a/src/Volo.Abp/Volo/Abp/Domain/Repositories/RepositoryBase.cs b/src/Volo.Abp/Volo/Abp/Domain/Repositories/RepositoryBase.cs index 1ec36046aa..1d78d64444 100644 --- a/src/Volo.Abp/Volo/Abp/Domain/Repositories/RepositoryBase.cs +++ b/src/Volo.Abp/Volo/Abp/Domain/Repositories/RepositoryBase.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; using System.Threading.Tasks; using Volo.Abp.Domain.Entities; @@ -74,5 +76,17 @@ namespace Volo.Abp.Domain.Repositories { return Task.FromResult(Count()); } + + protected static Expression> CreateEqualityExpressionForId(TPrimaryKey id) + { + var lambdaParam = Expression.Parameter(typeof(TEntity)); + + var lambdaBody = Expression.Equal( + Expression.PropertyOrField(lambdaParam, "Id"), + Expression.Constant(id, typeof(TPrimaryKey)) + ); + + return Expression.Lambda>(lambdaBody, lambdaParam); + } } }