Я прохожу следующий учебник по множественному сайту (https://app.pluralsight.com/library/courses/asp-dot-net-core-restful-api-building/table-of-contents) и пытаюсь применить знания к существующей базе данных, которую я имею в то же время, что и при создании базового приложения.
1) Я размещаюточка останова в начале AddAsset в AssetRepository.
2) Я посылаю следующий запрос POST в мой API:
POST http://localhost:6059/api/assets
{
"bay": "X",
"tile": "1",
"Serialnumber": "SERIAL",
"devicename": "DEVICENAME",
"assetspecs" : [
{
"assetattrid": "SIZE",
"numvalue":12
},
{
"assetattrid": "POWER",
"numvalue":24
}
]
}
3) CreateAsset запускается из AssetController, а AddAsset запускается изрепозиторий через контроллер
4) Отладчик встречает строку _assetRepository.AddAsset (assetEntity);и запускает AddAsset из репозитория
5) Прямо перед выполнением последней строки AssetRepository.AddAsset, (_context.Asset.Add (asset);) отладчик показывает мне, что у меня правильно сформирован набор записейс уникальными идентификаторами перед вводом строки - все выглядит нормально и как будто его нужно добавить в БД.
6) Я нажимаю клавишу f11, и отладчик переходит в мой контекстный файл и запускает OnConfiguring и OnModelCreating без проблем.затем обратно в действие контроллера CreateAsset, где он остановился.
7) Я нажимаю f11 СНОВА, и проверяется условие if (! _assetRepository.Save ()), которое вызывает принятие сообщения о том, что у меня неверное имя столбца.Assetuid.В выводе отладочной информации приложения столбец пишется с заглавной буквы, а все остальные столбцы начинаются со строчной буквы, которая казалась странной.
Я потратил на это полдня и затрудняюсь, если кто-нибудь сможет помочь.Есть еще несколько файлов, которые я не представляю, если вам нужно что-то увидеть дальше, пожалуйста, дайте мне знать и поблагодарить вас !!!!
aContext.cs
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Configuration;
namespace AssetAPI.Entities
{
public partial class aContext : DbContext
{
public aContext(DbContextOptions<aContext> options) : base(options)
{
}
public static IConfiguration Configuration;
public virtual DbSet<Asset> Asset { get; set; }
public virtual DbSet<Assetspec> Assetspec { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(Configuration["connectionStrings:AssetDBConnectionString"])
.EnableSensitiveDataLogging();
}
else
{
optionsBuilder.EnableSensitiveDataLogging();
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Asset>(entity =>
{
entity.HasKey(e => e.Assetuid)
.ForSqlServerIsClustered(false);
entity.ToTable("asset");
entity.HasIndex(e => e.Assetid)
.HasName("asset_indx7");
entity.HasIndex(e => e.Assetuid)
.HasName("asset_ndx")
.IsUnique();
entity.HasIndex(e => e.Barcode)
.HasName("asset_barcode");
entity.HasIndex(e => e.Pluscphyloc)
.HasName("asset_ndx16");
entity.HasIndex(e => e.Status)
.HasName("asset_ndx15");
entity.HasIndex(e => new { e.Assetnum, e.Assetuid })
.HasName("asset_ndx17");
entity.HasIndex(e => new { e.Assetnum, e.Siteid })
.HasName("asset_ndx11")
.IsUnique();
entity.HasIndex(e => new { e.Assetnum, e.Status })
.HasName("asset_ndx8");
entity.HasIndex(e => new { e.Orgid, e.Status })
.HasName("asset_ndx13");
entity.HasIndex(e => new { e.Siteid, e.Ancestor })
.HasName("asset_ndx7");
entity.HasIndex(e => new { e.Siteid, e.Assetnum })
.HasName("asset_ndx1")
.IsUnique()
.ForSqlServerIsClustered();
entity.HasIndex(e => new { e.Siteid, e.Calnum })
.HasName("asset_ndx4");
entity.HasIndex(e => new { e.Siteid, e.Location })
.HasName("asset_ndx6");
entity.HasIndex(e => new { e.Siteid, e.Parent })
.HasName("asset_ndx2");
entity.HasIndex(e => new { e.Siteid, e.Status })
.HasName("asset_ndx10");
entity.HasIndex(e => new { e.Siteid, e.Vendor })
.HasName("asset_ndx3");
entity.HasIndex(e => new { e.Assetid, e.Siteid, e.Moved })
.HasName("asset_ndx14")
.IsUnique();
entity.HasIndex(e => new { e.Assetnum, e.Location, e.Siteid })
.HasName("asset_ndx12");
entity.HasIndex(e => new { e.Itemnum, e.Siteid, e.Itemsetid })
.HasName("asset_ndx5");
entity.HasIndex(e => new { e.Siteid, e.Location, e.Parent })
.HasName("asset_ndx9");
entity.Property(e => e.Assetuid)
.HasColumnName("assetuid");
.ValueGeneratedNever();
..... Properties hidden, lots of them, came from scaffolding existing table
});
modelBuilder.Entity<Assetspec>(entity =>
{
entity.ToTable("assetspec");
entity.HasIndex(e => e.Assetspecid)
.HasName("assetspec_ndx")
.IsUnique();
entity.HasIndex(e => new { e.Assetattrid, e.Section })
.HasName("assetspec_ndx3");
entity.HasIndex(e => new { e.Assetnum, e.Siteid })
.HasName("assetspec_ndx4");
entity.HasIndex(e => new { e.Classstructureid, e.Assetattrid, e.Section })
.HasName("assetspec_ndx2");
entity.HasIndex(e => new { e.Assetattrid, e.Assetnum, e.Section, e.Siteid, e.Linearassetspecid })
.HasName("assetspec_ndx1")
.IsUnique();
entity.Property(e => e.Assetspecid)
.HasColumnName("assetspecid")
.ValueGeneratedNever();
... ..... Properties hidden, lots of them, came from scaffolding existing table
});
}
}
}
AssetRepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using AssetAPI.Entities;
namespace AssetAPI.Services
{
public class AssetRepository : IAssetRepository
{
private aContext _context;
public AssetRepository(aContext context)
{
_context = context;
}
public void AddAsset(Entities.Asset asset)
{
Random rnd = new Random();
asset.Assetid = rnd.Next(20000000, 30000000);
asset.Assetuid = rnd.Next(20000000, 30000000);
asset.Assetnum = rnd.Next(800000, 900000).ToString();
asset.Barcode = asset.Assetnum;
asset.Changedate = DateTime.Now;
asset.Changeby = "123";
asset.Langcode = "EN";
asset.Siteid = "SITE";
asset.Orgid = "ORG";
// the repository fills the id (instead of using identity columns)
if (asset.Assetspecs.Any())
{
foreach (var assetspec in asset.Assetspecs)
{
Random rnd2 = new Random();
assetspec.Assetspecid = rnd2.Next(20000000, 30000000);
assetspec.Changedate = DateTime.Today;
assetspec.Assetnum = asset.Assetnum;
assetspec.Classstructureid = "1140";
assetspec.Orgid = "ORG";
assetspec.Siteid = "SITE";
assetspec.Continuous = 0;
assetspec.Displaysequence = 0;
assetspec.Inheritedfromitem = 0;
assetspec.Itemspecvalchanged = 0;
assetspec.Mandatory = 0;
}
}
_context.Asset.Add(asset);
}
public void AddAssetspecForAsset(string assetnum, Assetspec assetspec)
{
var asset = GetAsset(assetnum);
if (asset != null)
{
assetspec.Assetnum = assetnum;
assetspec.Changeby = "123";
assetspec.Changedate = DateTime.Now;
assetspec.Classstructureid = "1140";
assetspec.Orgid = "ORG";
assetspec.Siteid = "SITE";
// if there isn't an id filled out (ie: we're not upserting),
// we should generate one
if (assetspec == null)
{
Random rnd2 = new Random();
assetspec.Assetspecid = rnd2.Next(20000000, 30000000);
assetspec.Assetattrid = "RUSZ";
assetspec.Numvalue = 12;
}
asset.Assetspecs.Add(assetspec);
}
}
public bool AssetExists(string assetnum)
{
return _context.Asset.Any(a => a.Assetnum == assetnum);
}
public Asset GetAsset(string assetnum)
{
return _context.Asset.FirstOrDefault(a => a.Assetnum == assetnum);
}
public IEnumerable<Entities.Asset> GetAssets()
{
// return _context.Asset.OrderBy(a => a.Barcode).ThenBy(a => a.Bay).ThenBy(a => a.Tile).Take(10).ToList();
return _context.Asset.OrderByDescending(a => a.Bay).ThenBy(a => a.Tile).Take(10).ToList();
}
public IEnumerable<Entities.Asset> GetAssets(IEnumerable<string> Assetnums)
{
return _context.Asset.Where(a => Assetnums.Contains(a.Assetnum))
.OrderBy(a => a.Barcode)
.OrderBy(a => a.Bay)
.OrderBy(a => a.Tile)
.ToList();
}
public IEnumerable<Assetspec> GetAssetspecsForAsset(string assetnum)
{
return _context.Assetspec
.Where(b => b.Assetnum == assetnum && b.Assetattrid == "RUSZ").OrderBy(b => b.Assetnum).ToList();
}
public bool Save()
{
return (_context.SaveChanges() >= 0);
}
public Assetspec GetAssetspecsForAsset(string assetnum, long assetspecId)
{
return _context.Assetspec
.Where(b => b.Assetnum == assetnum && b.Assetspecid == assetspecId).FirstOrDefault();
}
}
}
Asset.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AssetAPI.Entities
{
public partial class Asset
{
[Key]
public long Assetuid { get; set; }
public string Bay { get; set; }
public string Tile { get; set; }
public string TileLocation { get; set; }
public string Serialnumber { get; set; }
public string Devicename { get; set; }
....scaffolded properties hidden
public virtual ICollection<Assetspec> Assetspecs { get; set; } = new List<Assetspec>();
}
}
AssetsController.cs
using AssetAPI.Models;
using AssetAPI.Services;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using AssetAPI.Entities;
namespace AssetAPI.Controllers
{
[Route("api/assets")]
public class AssetsController : Controller
{
private IAssetRepository _assetRepository;
public AssetsController(IAssetRepository assetRepository)
{
_assetRepository = assetRepository;
}
public IActionResult GetAssets()
{
var assetsFromRepo = _assetRepository.GetAssets();
var assets = Mapper.Map<IEnumerable<AssetDTO>>(assetsFromRepo);
return Ok(assets);
}
[HttpGet("{assetnum}", Name = "GetAsset")]
public IActionResult GetAsset(string assetnum)
{
var assetFromRepo = _assetRepository.GetAsset(assetnum); //Run GetAsset method for the passed in Assetid from AssetRepository
if (assetFromRepo == null)
{
return NotFound();
}
var asset = Mapper.Map<AssetDTO>(assetFromRepo); //Map the entity to the DTO
return Ok(asset); //Return the result in JSON format
}
//[FromBody] attribute signifies that parameter should be serialized from the request body into AssetForCreationDTO
[HttpPost]
public IActionResult CreateAsset([FromBody] AssetForCreationDTO asset)
{
//If the input provider in the request body was correctly serialized to an AssetForCreationDTO
if (asset == null)
{
return BadRequest();
}
var assetEntity = Mapper.Map<Asset>(asset); //Map the entity to the DTO
_assetRepository.AddAsset(assetEntity); //Add the entity to the DBContext
if (!_assetRepository.Save()) //If the new resource cannot be saved
{
throw new Exception("Creating asset failed upon save");
return StatusCode(500, "A problem occured.");
}
//Map the results again to learn the ID of the newly created resource
var assetToReturn = Mapper.Map<AssetDTO>(assetEntity);
//In case of a successful post, return 201 created response with location header
//First param = name of route
//Second = anon type containing new resource id
//Third = Response body of newly created resource
return CreatedAtRoute("GetAsset", new { assetnum = assetToReturn.assetnum }, assetToReturn);
}
}
}
AssetDTO.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AssetAPI.Models
{
public class AssetDTO
{
public string assetnum { get; set; }
public string Barcode { get; set; }
public string Bay { get; set; }
public string Tile { get; set; }
public string TileLocation { get; set; }
public string Serialnumber { get; set; }
public string Devicename { get; set; }
}
}
AssetForCreationDTO:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AssetAPI.Models
{
public class AssetForCreationDTO
{
public string Bay { get; set; }
public string Tile { get; set; }
public string TileLocation { get; set; }
public string Serialnumber { get; set; }
public string Devicename { get; set; }
public ICollection<AssetspecForCreationDTO> Assetspecs { get; set; } = new List<AssetspecForCreationDTO>();
}
}