当前位置:网站首页>ASP. Net core development experience

ASP. Net core development experience

2022-06-22 07:24:00 Running water I love

ASP.NET Core Development experience

ASP.NET Core Development experience

One 、c# grammar

Asynchronous methods

It can be done by async、await、Task Compose a business method that supports asynchrony ,

Use async Define asynchronous methods ,await Define asynchronous functions ,Task Define the asynchronous return result

public async Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds)
        {
    
            if (companyIds == null)
            {
    
                throw new ArgumentNullException(nameof(companyIds));
            }

            return await _context.Companies
                .Where(x => companyIds.Contains(x.Id))
                .OrderBy(x => x.Name)
                .ToListAsync();
        }

Common abnormal

throw new ArgumentNullException(nameof(companyIds));	//  Judge whether the method parameter is empty 

Guid class

GUIDglobally unique identifier( Globally unique identifier )

Equivalent to an algorithm generated ID

Guid.Empty()Guid Structure , Its value is all zero ., Generally used to judge Guid Whether it has been assigned

new Guid(): Return from 00000000-0000-0000-0000-000000000000 Composed of Guid object

Guid.NewGuid(): Returns a set of generated by random numbers Guid object

Guid.Parse(string guidString): Convert the string to Guid object

Console.WriteLine(Guid.Parse("fc6a01da-c1bc-44c6-a36a-d0fb02550af6"));

Two 、WebAPI

1. establish WebAPI Project configuration

To configure Startup.cs

public class Startup
    {
    
    		public void ConfigureServices(IServiceCollection services)
        {
    
          //  Add support for content negotiation (XML)JSON first 
        	services.AddControllers(setup =>
            {
    
                setup.ReturnHttpNotAcceptable = true;
            }).AddXmlDataContractSerializerFormatters();
        }
  			public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
    
          //  Add simple support for exception handling production environments 
            if (env.IsDevelopment())
            {
    
                app.UseDeveloperExceptionPage();
            }
            else
            {
    
                app.UseExceptionHandler(appBuilder =>
                {
    
                    appBuilder.Run(async context =>
                    {
    
                        context.Response.StatusCode = 500;
                        await context.Response.WriteAsync("Unexpected Error");
                    });
                });
            }
          	
          //  take Https Forward to Http
          	app.UseHttpsRedirection();
					
            app.UseRouting();

            app.UseAuthorization();
						
          	//  Be careful : The routing template must be configured separately in the controller 
            app.UseEndpoints(endpoints => {
     endpoints.MapControllers(); });
        }
    }

Be careful : The routing template must be configured separately in the controller

** Be careful :** If you want to configure content negotiation XML first , The following codes can be configured

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
    
            services.AddControllers(setup =>
            {
    
                setup.ReturnHttpNotAcceptable = true;
              // OutputFormatters Different support for content negotiation can be added in , The first is the default serial number support 
                setup.OutputFormatters
                  .Add(new XmlDataContractSerializerOutputFormatter());
            });
        }

2. To configure WebAPI Controller and general routing configuration

Routing configuration , Write on the notes

Simple routing configuration

[ApiController]		
[Route("api/companies")]
public class CompaniesController : ControllerBase
{
    
	[HttpGet("api/companies")]
	public async Task<ActionResult> GetCompanies()
	{
    
		var companies = await _companyRepository.GetCompaniesAsync();    
		return Ok(companyDtos);
	}
  
  [HttpGet("{companyId}")]
	public async Task<ActionResult> GetCompany(Guid companyId)
	{
    
		var company = await _companyRepository.GetCompanyAsync(companyId);
    if(company == null)
    {
    
      return NotFound();
    }      
		return Ok(companyDtos);
	}
}

Optional [Route("api/companies")] Configure to [Route("api/[controller]")]

This is the time ,[controller] Consistent with the controller name .

Can be [HttpGet("{companyId}")] Write separately :

[HttpGet]
[Route("{companyId}")]

It can be globally simplified to

[ApiController]		
[Route("api/companies")]
public class CompaniesController : ControllerBase
{
    
	[HttpGet]
	public async Task<ActionResult> GetCompanies()
	{
    
		var companies = await _companyRepository.GetCompaniesAsync();    
		return Ok(companyDtos);
	}
  
  [HttpGet]
	public async Task<ActionResult> GetCompany(Guid companyId)
	{
    
		var company = await _companyRepository.GetCompanyAsync(companyId);
    if(company == null)
    {
    
      return NotFound();
    }      
		return Ok(companyDtos);
	}
}

3. Configure the default startup page

Properties/launchSettings.json

Configure the following "launchUrl": "api/companies"

"profiles": {
    
    "IIS Express": {
    
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/companies",
      "environmentVariables": {
    
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "RoutineApi2": {
    
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/companies",
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
    
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }

4.Enity Model And externally oriented Model

In one case , take EF Built in Model, External output and interface parameter transfer Mode(DTO) Separate .

Create three folders to store three different types of storage Model Folder

  • RoutineApi2/Entities
    • Company.cs
    • Employee.cs
    • Gender.cs
  • Models
    • CompanyDto.cs
    • EmployeeDto.cs
  • DtoParameters
    • CompanyDtoParameters
    • EmployeeDtoParameters

3、 ... and 、EF Core relevant

1. EFCore Create the entity class and complete the mapping (CodeFirst)

Step one : Build a one to many relationship
  • RoutineApi2/Entities
    • Company.cs
    • Employee.cs
    • Gender.cs
public class Company
    {
    		
  			//  To configure ID
        public Guid Id {
     get; set; }
        public string Name {
     get; set; }
        public string Introduction {
     get; set; }
  			//  add to Employees aggregate ( One to many )
        public ICollection<Employee> Employees {
     get; set; }
    }

public class Employee
    {
    
  			//  To configure ID
        public Guid Id {
     get; set; }
        public Guid CompanyId {
     get; set; }
        public string EmployeeNo {
     get; set; }
        public string FirstName {
     get; set; }
        public string LastName {
     get; set; }
        public Gender Gender {
     get; set; }
        public DateTime DataOfBirth {
     get; set; }
  			//  Configure an external association 
        public Company Company {
     get; set; }
    }

public enum Gender
    {
    
         male  = 1,
         Woman  = 2
    }
Step two : add to nuget package :

​ Microsoft.EntityFrameworkCore.SqlServer

​ Microsoft.EntityFrameworkCore.Sqlite

​ Microsoft.EntityFrameworkCore.Tools

Step three : Add data sources

RoutineApi2/Data/RoutineDbContext.cs

namespace RoutineApi2.Data
{
    
    public class RoutineDbContext : DbContext
    {
    	
      	//  Default configuration injection 
        public RoutineDbContext(DbContextOptions<RoutineDbContext> options) : base(options)
        {
    }
				
      	//  Database dataset Injection 
        public DbSet<Company> Companies {
     get; set; }
        public DbSet<Employee> Employees {
     get; set; }
				
      	//  Configure associations and restrictions 
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
    
            modelBuilder.Entity<Company>()
                .Property(x => x.Name).IsRequired().HasMaxLength(100);
            modelBuilder.Entity<Company>()
                .Property(x => x.Introduction).IsRequired().HasMaxLength(500);
            modelBuilder.Entity<Employee>()
                .Property(x => x.EmployeeNo).IsRequired().HasMaxLength(10);
            modelBuilder.Entity<Employee>()
                .Property(x => x.FirstName).IsRequired().HasMaxLength(50);
            modelBuilder.Entity<Employee>()
                .Property(x => x.LastName).IsRequired().HasMaxLength(50);
            modelBuilder.Entity<Employee>()
                .HasOne(x => x.Company)
                .WithMany(x => x.Employees)
              	//  When Employee Exist in Company, Not delete Company
                .HasForeignKey(x => x.CompanyId).OnDelete(DeleteBehavior.Restrict); 
          
            //  Configure seed data 
            modelBuilder.Entity<Company>().HasData(
                new Company
                {
    
                    Id = Guid.Parse("25dbd774-ae0e-44d2-94a1-58d5805da533"),
                    Name = "Microsoft",
                    Introduction = "Great Company",
                },
                new Company
                {
    
                    Id = Guid.Parse("2aea0972-6a03-4f3c-9672-04fa2ca99110"),
                    Name = "Google",
                    Introduction = "Don't be evil"
                    
                },
                new Company
                {
    
                    Id = Guid.Parse("c6fbfe31-590f-477f-a87a-3c68423909c6"),
                    Name = "Alipapa",
                    Introduction = "Fubao Company"
                }
            );
            modelBuilder.Entity<Employee>().HasData(
                new Employee
                {
    
                    Id = Guid.Parse("410f4bbe-e109-49d4-932a-e3cfe29f53ed"),
                    CompanyId = Guid.Parse("25dbd774-ae0e-44d2-94a1-58d5805da533"),
                    DataOfBirth = new DateTime(1966,1,2),
                    EmployeeNo = "MSFT231",
                    FirstName = "Nick",
                    LastName = "Carer",
                    Gender = Gender. male 
                },
                new Employee
                {
    
                    Id = Guid.Parse("ba5790e1-765d-4e71-8795-edd24398f8e4"),
                    CompanyId = Guid.Parse("25dbd774-ae0e-44d2-94a1-58d5805da533"),
                    DataOfBirth = new DateTime(1996,2,3),
                    EmployeeNo = "MSFT245",
                    FirstName = "Vince",
                    LastName = "Carter",
                    Gender = Gender. male 
                },
                new Employee
                {
    
                    Id = Guid.Parse("1a5b77ee-9e43-46ba-b1dc-3b5c32c647d4"),
                    CompanyId = Guid.Parse("2aea0972-6a03-4f3c-9672-04fa2ca99110"),
                    DataOfBirth = new DateTime(1986,2,1),
                    EmployeeNo = "MSFT215",
                    FirstName = "Machal",
                    LastName = "Jeckson",
                    Gender = Gender. male 
                }
            );
        }
    }
}
Step four : Configuration database connection string

One 、SQLServer edition :

​ appsettings.json

"ConnectionStrings": {
    
    "DockerDBConnection": "Data Source=127.0.0.1;Initial Catalog=CompanyDB;User ID=sa;Password=<Admin123456>",
    "LocalDockerDBConnection": "Data Source=192.168.1.104;Initial Catalog=CompanyDB;User ID=sa;Password=<Admin123456>",
    "MSDBConnection": "Server=(localdb)\\mssqllocaldb;Database=CompanyDB;Trusted_Connection=True;MultipleActiveResultSets=true",
    "SqlServerConnection": "Data Source = myServerAddress;Initial Catalog = myDataBase;User Id = myUsername;Password = myPassword;"
  }

​ Startup.cs

public Startup(IConfiguration configuration)
{
    
	_configuration = configuration;
}

public void ConfigureServices(IServiceCollection services)
{
    
	//  Database connection service 
		services.AddDbContextPool<AppDbContent>(
		option => option
      .UseSqlServer(_configuration.GetConnectionString("LocalDockerDBConnection")));
}

Two 、Sqlite edition

​ Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
    
        	services.AddDbContextPool<RoutineDbContext>(
                option =>
                {
    
                    option.UseSqlite("Data Source=routine.db");
                });
        }
Step five : Create migration file

VSCode Development

Shell The input

$ dotnet ef migrations add InitialMigration

VS Development

Open the package console

Enter the command

$ add-migration

You can see the following files in the directory

  • Migrations
    • 20200511033121_InitialMigration.cs
    • RoutineDbContextModelSnapshot.cs
Step six : Start the program , Perform the migration
Step seven : Load the database connection pool into the service class
public class CompanyRepository : ICompanyRepository
{
    
	private readonly RoutineDbContext _context;
	public CompanyRepository(RoutineDbContext context)
	{
    
  	_context = context ?? throw new ArgumentException(nameof(context));
  }
}

2. Commonly used Linq Statement summary

One 、 Query all the data

No parameter , Return all data sets directly

public async Task<IEnumerable<Company>> GetCompaniesAsync()
{
    
	return await _context.Companies.ToListAsync();
}            
Two 、 Single data condition query

Single parameter , Return single data

public Task<Company> GetCompanyAsync(Guid companyId)
{
    
	if (companyId == Guid.Empty)
	{
    
		throw new ArgumentNullException(nameof(companyId));
	}
  // FirstOrDefaultAsync :  Returns a unique object asynchronously 
	return _context.Companies.FirstOrDefaultAsync(x => x.Id == companyId);
}
3、 ... and 、 Set parameter condition query

Parameters are data sets , Return data set

public async Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds)
{
    
	if (companyIds == null)
	{
    
  	throw new ArgumentNullException(nameof(companyIds));
	}
  return await _context.Companies
    .Where(x => companyIds.Contains(x.Id))
		.OrderBy(x => x.Name)
		.ToListAsync();
}
Four 、 Multi parameter conditional query

Parameters : multi-parameter , return : Single data object

public async Task<Employee> GetEmployeesAsync(Guid companyId, Guid employeeId)
{
    
	if (companyId == Guid.Empty)
  {
    
		throw new ArgumentNullException(nameof(companyId));
	}
  
  if (companyId == Guid.Empty)
  {
    
  	throw new ArgumentNullException(nameof(companyId));
  }
	
  //  Multiconditional query 
  return await _context.Employees
                .FirstOrDefaultAsync(x => x.CompanyId == companyId && x.Id == employeeId);
        }
5、 ... and 、 Add data to database
public void AddCompany(Company company)
{
    
	if (company == null)
	{
    
  	throw new ArgumentNullException(nameof(company));
	}
  
  //  Process incoming data 
  	company.Id = Guid.NewGuid();
    foreach (var employee in company.Employees)
    {
    
    	employee.Id = Guid.NewGuid();   
    }
   	
  //  Add data 
		_context.Companies.Add(company);
}
6、 ... and 、 Update data
public void UpdateCompany(Company company)
{
    
	// _context.Entry(company).State = EntityState.Modified;  Don't write 
}
7、 ... and 、 Delete data
public void DeleteCompany(Company company)
{
    
	if (company == null)
  {
    
  	throw new ArgumentNullException(nameof(company));
  }
  //  Delete data 
	_context.Companies.Remove(company);
}
8、 ... and 、 Verify that the data exists in the database
 public async Task<bool> CompanyIsExistsAsync(Guid companyId)
{
    
	if (companyId == Guid.Empty)
  {
    
  	throw new ArgumentNullException(nameof(companyId));
	}
	return await _context.Companies.AnyAsync(x => x.Id == companyId);
}
Nine 、 Save database collection
public async Task<bool> SaveAsync()
{
    
	return await _context.SaveChangesAsync() >= 0;
}
Ten 、 Complex queries ( Filter ), Fuzzy query ( Search for )
public async Task<IEnumerable<Employee>> 
  					//  company ID( Query criteria ), Employee gender ( Filter ), Fuzzy query ( Search for )q
            GetEmployeesAsync(Guid companyId, string genderDisplay,string q)
        {
    
            if (companyId == Guid.Empty)
            {
    
                throw new ArgumentNullException(nameof(companyId));
            }
						
  					//  If the filter and search criteria passed in are empty , Regular short answer queries 
            if (string.IsNullOrWhiteSpace(genderDisplay) && string.IsNullOrWhiteSpace(q))
            {
    
                return await _context.Employees
                    .Where(x => x.CompanyId == companyId)
                    .OrderBy(x => x.EmployeeNo)
                    .ToListAsync();
            }
            
  					//  First, perform a simple query and save the result as items
            var items = 
                _context.Employees.Where(x => x.CompanyId == companyId);
						
            if (!string.IsNullOrWhiteSpace(genderDisplay))
            {
    
              	// Trim() Remove the spaces on both sides 
                genderDisplay = genderDisplay.Trim();
              	//  Convert the passed in parameter to Enum type 
                var gender = Enum.Parse<Gender>(genderDisplay);

                items = items.Where(x => x.Gender == gender);
            }

            if (!string.IsNullOrWhiteSpace(q))
            {
    
                q = q.Trim();
              	//  Any match will do || or 
                items = items.Where(x => x.EmployeeNo.Contains(q)
                                         || x.FirstName.Contains(q)
                                         || x.LastName.Contains(q)
                                         );
            }
  
            return await items.OrderBy(x => x.EmployeeNo)
                .ToListAsync();
        }
11、 ... and 、 Pass in the object as the parameter list of the query

DtoParameters/CompanyDtoParameters.cs

public class CompanyDtoParameters
{
    
		public string CompanyName {
     get; set; }
  	public string SearchTerm {
     get; set; }
}
public async Task<IEnumerable<Company>> GetCompaniesAsync(CompanyDtoParameters parameters)
        {
    
            if (parameters == null)
            {
    
                throw new ArgumentNullException(nameof(parameters));
            }

            if (string.IsNullOrWhiteSpace(parameters.CompanyName) && 
                string.IsNullOrWhiteSpace(parameters.SearchTerm))
            {
    
                return await _context.Companies.ToListAsync();
            }
						
  					//  Save the database connection string collection temporarily , The query method is not triggered here 
            var queryExpression = _context.Companies as IQueryable<Company>;
            if (!string.IsNullOrWhiteSpace(parameters.CompanyName))
            {
    
                parameters.CompanyName = parameters.CompanyName.Trim();
                queryExpression = queryExpression
                    .Where(x => x.Name == parameters.CompanyName);
            }

            if (!string.IsNullOrWhiteSpace(parameters.SearchTerm))
            {
    
                parameters.SearchTerm = parameters.SearchTerm.Trim();
              	//  Fuzzy query 
                queryExpression = queryExpression
                    .Where(x => x.Name.Contains(parameters.SearchTerm)
                    || x.Introduction.Contains(parameters.SearchTerm));
            }
            
            //  Only here can we really query the database 
            return await queryExpression.ToListAsync();
        }
!!! Experience

​ Summary of common methods :

​ One 、 After the parameter is passed in, you need to determine whether it is empty

//  The incoming type is Guid
if (companyId == Guid.Empty)
{
    
		throw new ArgumentNullException(nameof(companyId));
}
//  The incoming type is object 
if (companyIds == null)
{
    
		throw new ArgumentNullException(nameof(companyIds));
}
//  The incoming type is string
if (string.IsNullOrWhiteSpace(genderDisplay) && string.IsNullOrWhiteSpace(q)){
    }

​ Two 、 The query result is unique , use FirstOrDefaultAsync(), A special kind Where

return _context.Companies.FirstOrDefaultAsync(x => x.Id == companyId);

​ 3、 ... and 、 The query result is not unique , use Where

​ Four 、 The query results need to be sorted , have access to OrderBy() and OrderByDescending(), Sort according to the positional parameter

return await _context.Companies
  							.Where(x => companyIds.Contains(x.Id))
                .OrderBy(x => x.Name)
                .ToListAsync();

​ 5、 ... and 、 Parameters should be first Trim Remove the extra space and then perform the query operation

​ 6、 ... and 、 Determine whether the data exists in the database , have access to AnyAsync Method , Be similar to Where, But what it returns is Bool type

return await _context.Companies.AnyAsync(x => x.Id == companyId);

​ 7、 ... and 、 To add, delete and delete data, you can use DBSet.Add(Object) and DBSet.Remove(Object)

Four 、AutoMapper

When frequent need for DTO When mapping data , Need new a large number of DTO object , Such code is redundant .

have access to AutoMapper Finish right DTO Automatic mapping of .

Step one 、 add to AutoMapper Of Nuget package

AutoMapper.Extensions.Microsoft.DependencyInjection

Step two 、 stay Startup Of ConfigureService register Mapper Containers , Register default configuration
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
Step three 、 To configure Mapper mapping

establish Profiles Folder

  • Profiles
    • RoutineApi2/Profiles/CompanyProfile.cs
    • RoutineApi2/Profiles/EmployeeProfile.cs

Source type :

public class Company
    {
    
        public Guid Id {
     get; set; }
        public string Name {
     get; set; }
        public string Introduction {
     get; set; }
        public ICollection<Employee> Employees {
     get; set; }
    }

public class Employee
    {
    
        public Guid Id {
     get; set; }
        public Guid CompanyId {
     get; set; }
        public string EmployeeNo {
     get; set; }
        public string FirstName {
     get; set; }
        public string LastName {
     get; set; }
        public Gender Gender {
     get; set; }
        public DateTime DataOfBirth {
     get; set; }
        public Company Company {
     get; set; }
    }

public enum Gender
    {
    
         male  = 1,
         Woman  = 2
    }

public class CompanyDto
    {
    
        public Guid Id {
     get; set; }
        public string CompanyName {
     get; set; }
    }

public class EmployeeDto
    {
    
        public Guid Id {
     get; set; }
        public Guid CompanyId {
     get; set; }
        public string EmployeeNo {
     get; set; }
        public string Name {
     get; set; }
        public Gender GenderDisplay {
     get; set; }
        public int Age {
     get; set; } 
    }

To configure Mapper

public class CompanyProfile : Profile
    {
    
        public CompanyProfile()
        {
    
            //  Original type and target type 
            CreateMap<Company, CompanyDto>()
                .ForMember(
                    dest => dest.CompanyName,
                    opt 
                        => opt.MapFrom(src => src.Name));
        }  
    }

public class EmployeeProfile : Profile
    {
    
        public EmployeeProfile()
        {
    
            CreateMap<Employee, EmployeeDto>()
                .ForMember(
                    dest
                        => dest.Name,
                    opt
                        => opt.MapFrom(src
                            => $"{src.FirstName} {src.LastName}"))
                .ForMember(
                    dest
                        => dest.GenderDisplay,
                    opt
                        => opt.MapFrom(src
                            => src.Gender.ToString()))
                .ForMember(
                    dest
                        => dest.Age,
                    opt
                        => opt.MapFrom(src
                            => DateTime.Now.Year - src.DataOfBirth.Year));
        }
    }
Step five 、 add to Mapper To the controller
public class CompaniesController : ControllerBase
    {
    
        private readonly ICompanyRepository _companyRepository;
        private readonly IMapper _mapper; 

        public CompaniesController(ICompanyRepository companyRepository, IMapper mapper)
        {
    
            _companyRepository = companyRepository ??
                                 throw new ArgumentNullException(nameof(companyRepository));
            _mapper = mapper ?? throw new ArgumentException(nameof(mapper));
        }
        
        [HttpGet]
        [HttpHead]
        public async Task<ActionResult<IEnumerable<CompanyDto>>> 
            GetCompanies([FromQuery]CompanyDtoParameters parameters)
        {
    
            var companies = await _companyRepository.GetCompaniesAsync(parameters);
						
          	//  Automatically complete the mapping , The parameter is the source Model, The generic is the target type 
            var companyDtos = _mapper.Map<IEnumerable<CompanyDto>>(companies);
            
            return Ok(companyDtos);
        }
  		
  		 [HttpGet("{companyId}")]
       public async Task<ActionResult<CompanyDto>> GetCompany(Guid companyId)
       {
    
            var company = await _companyRepository.GetCompanyAsync(companyId);
            
            if (company == null)
            {
    
                return NotFound();
            }
            return Ok(_mapper.Map<CompanyDto>(company));
       }
	}
原网站

版权声明
本文为[Running water I love]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202220536274645.html