試圖跟隨 .net core 快速开发框架 WTM系列视频教程 中去做練習, 但發生了以下的錯誤

发布于 2020-07-09 00:49:18

試圖跟隨 .net core 快速开发框架 WTM系列视频教程 中去做練習, 但發生了以下的錯誤, 查找了一段時間也找不到原因, 請教各位有何建議, 煩請指導一下.

剛看完Code First视頻:
https://www.bilibili.com/video/av86527514/?p=3

所有Model都成功在數據庫中建立.

City, Hospital 及 Control Center GenCode沒問題
但 Virus, Patient 及 Report GenCode 有問题

  1. PatientVM: Cannot implicitly convert type '<System.Guid?>' to '<System.Guid>'
  2. VirusVM, ReportImportVM:'PatientVirus' does not contain a definition for 'PatientIdNumber'
  3. Patient 表中也有點怪, ID 並非主鍵, 而主鍵是IDNumber 這正常嗎?

我的所有代碼可在GitHub找到
https://github.com/PancoCheong/WTM_ERCS.git

1>------ Rebuild All started: Project: ERCS.Model, Configuration: Debug Any CPU ------
1>ERCS.Model -> C:\repos\WTM_ERCS\ERCS.Model\bin\Debug\netcoreapp3.1\ERCS.Model.dll
2>------ Rebuild All started: Project: ERCS.DataAccess, Configuration: Debug Any CPU ------
3>------ Rebuild All started: Project: ERCS.ViewModel, Configuration: Debug Any CPU ------
2>ERCS.DataAccess -> C:\repos\WTM_ERCS\ERCS.DataAccess\bin\Debug\netcoreapp3.1\ERCS.DataAccess.dll
3>C:\repos\WTM_ERCS\ERCS.ViewModel\Disease\PatientVMs\PatientVM.cs(33,34,33,81): error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<System.Guid?>' to 'System.Collections.Generic.List<System.Guid>'
3>C:\repos\WTM_ERCS\ERCS.ViewModel\Data\VirusVMs\VirusVM.cs(27,66,27,81): error CS1061: 'PatientVirus' does not contain a definition for 'PatientIdNumber' and no accessible extension method 'PatientIdNumber' accepting a first argument of type 'PatientVirus' could be found (are you missing a using directive or an assembly reference?)
3>C:\repos\WTM_ERCS\ERCS.ViewModel\Data\VirusVMs\VirusVM.cs(37,60,37,75): error CS0117: 'PatientVirus' does not contain a definition for 'PatientIdNumber'
3>C:\repos\WTM_ERCS\ERCS.ViewModel\Data\VirusVMs\VirusVM.cs(49,110,49,125): error CS0117: 'PatientVirus' does not contain a definition for 'PatientIdNumber'
3>C:\repos\WTM_ERCS\ERCS.ViewModel\Disease\ReportVMs\ReportImportVM.cs(20,88,20,103): error CS1061: 'Report' does not contain a definition for 'PatientIdNumber' and no accessible extension method 'PatientIdNumber' accepting a first argument of type 'Report' could be found (are you missing a using directive or an assembly reference?)
3>Done building project "ERCS.ViewModel.csproj" -- FAILED.
4>------ Rebuild All started: Project: ERCS, Configuration: Debug Any CPU ------
4>C:\Program Files\dotnet\sdk\3.1.301\Sdks\Microsoft.NET.Sdk.Razor\build\netstandard2.0\Microsoft.NET.Sdk.Razor.MvcApplicationPartsDiscovery.targets(54,5): warning RAZORSDK1007: Reference assembly C:\repos\WTM_ERCS\ERCS.ViewModel\bin\Debug\netcoreapp3.1\ERCS.ViewModel.dll could not be found. This is typically caused by build errors in referenced projects.
4>CSC : error CS0006: Metadata file 'C:\repos\WTM_ERCS\ERCS.ViewModel\bin\Debug\netcoreapp3.1\ERCS.ViewModel.dll' could not be found
4>Done building project "ERCS.csproj" -- FAILED.
5>------ Rebuild All started: Project: ERCS.Test, Configuration: Debug Any CPU ------
5>C:\Program Files\dotnet\sdk\3.1.301\Sdks\Microsoft.NET.Sdk.Razor\build\netstandard2.0\Microsoft.NET.Sdk.Razor.MvcApplicationPartsDiscovery.targets(54,5): warning RAZORSDK1007: Reference assembly C:\repos\WTM_ERCS\ERCS\bin\Debug\netcoreapp3.1\ERCS.dll could not be found. This is typically caused by build errors in referenced projects.
5>CSC : error CS0006: Metadata file 'C:\repos\WTM_ERCS\ERCS\bin\Debug\netcoreapp3.1\ERCS.dll' could not be found
5>CSC : error CS0006: Metadata file 'C:\repos\WTM_ERCS\ERCS.ViewModel\bin\Debug\netcoreapp3.1\ERCS.ViewModel.dll' could not be found
5>Done building project "ERCS.Test.csproj" -- FAILED.
========== Rebuild All: 2 succeeded, 3 failed, 0 skipped ==========
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Cryptography;
using System.Text;
using WalkingTec.Mvvm.Core;

namespace ERCS.Model
{
    public enum GenderEnum
    {
        [Display(Name = "男")]     //**key** can set attribute to Enum
        Male,
        [Display(Name = "女")]     
        Female
    }

    public enum PatientStatusEnum
    {
        [Display(Name = "無症狀")]     // can set attribute to Enum
        Asymptomatic,
        [Display(Name = "疑似")]
        Suspected,
        [Display(Name = "確診")]
        Diagnosed,
        [Display(Name = "治癒")]
        Cured,
        [Display(Name = "死亡")]
        Death
    }

    [Table("MyPatients")]  //**key** Define different name in Database; however, Patients is still being used in code level
    public class Patient : PersistPoco
    {
        // **key**
        // TopBasePoco <-- BasePoco <-- PresistPoco
        // BasePoco has 4 more properties than TopBasePoco: CreateTime, CreateBy, UpdateTime, UpdateBy
        // PersistPoco has 1 more property than BasePoco: IsValid  (avoid physically delete record, just marked invalid)

        //**key** These two lines override the WTM default data type for ID column (ie. GUID) 
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public new int ID { get; set; }

        [Display(Name = "患者名稱")]
        [Required(ErrorMessage = "患者名稱是必填欄位")]
        public string PatientName { get; set; }

        [Display(Name = "證件號碼")]
        [Required(ErrorMessage = "證件號碼是必填欄位")]
        [RegularExpression("^(\\d{18,18}|\\d{15,15}|\\d{17,17}x)", ErrorMessage = "證件號碼格式不正確")]
        public string IdNumber { get; set; }

        // **key**
        // search baidu: 身份证正则表达式
        // https://blog.csdn.net/weixin_44588757/article/details/89968629
        // omit / at the beginning and the end /

        [Display(Name = "性別")]
        [Required(ErrorMessage = "性別是必填欄位")]

        public GenderEnum? Gender { get; set; }     // ? means optional, it allows UI to show "please select a value" on drop-down list

        [Display(Name = "患者狀態")]
        [Required(ErrorMessage = "患者狀態是必填欄位")]
        public PatientStatusEnum? Status { get; set; }

        [Display(Name = "出生日期")]
        [Required(ErrorMessage = "出生日期是必填欄位")]
        public DateTime? Birthday { get; set; }     // ? means optional, it allows UI to show "please select date" on date picker

        //**key**
        [NotMapped]     // this property will not map to database, only available in code level
        public int Age { get
            {
                return DateTime.Now.Year - Birthday.Value.Year;
            }
        }

        // Location and LocationId are tied together to create a table relationship
        // one-to-many relationship: one City to many Hospital
        [Display(Name = "藉貫")]
        public Location Location { get; set; }      //create relationship with City
        //[Display(Name = "藉貫")]
        //[Required(ErrorMessage = "藉貫是必填欄位")]
        public Guid? LocationId { get; set; }    //Foreign Key

        [Display(Name = "所屬醫院")]
        public Hospital Hospital { get; set; }      //create relationship with City
        //[Display(Name = "醫院名稱")]
        //[Required(ErrorMessage = "醫院名稱是必填欄位")]
        public Guid? HospitalId { get; set; }    //Foreign Key


        [Display(Name = "相片")]
        public FileAttachment Photo { get; set; }      //create relationship with City
        //[Display(Name = "相片")]
        public Guid? PhotoId { get; set; }    //Foreign Key

        // Many-to-Many relationship
        [Display(Name = "病毒")]
        public List<PatientVirus> Viruses { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Attributes;

namespace ERCS.Model
{
    [MiddleTable] //WTM Framework attribute to define many-to-many relationship

    // Many-to-Many Relationship
    // it is just 2 one-to-many relationships,
    // which requires this 3rd table (middle table) to store the relationship information
    // Patient and Virus tables has a LIST that points to this table
    public class PatientVirus : TopBasePoco
    {
        //[Display(Name = "患者名稱")]
        public Patient Patient { get; set; }
        //[Display(Name = "患者名稱")]
        //[Required(ErrorMessage = "患者名稱是必填欄位")]
        public int? PatientId { get; set; } //Foreign Key (GUID is overrided by integer)

        //[Display(Name = "病毒名稱")]
        public Virus Virus { get; set; }
        //[Display(Name = "病毒名稱")]
        //[Required(ErrorMessage = "病毒名稱是必填欄位")]
        public Guid? VirusId { get; set; } //Foreign Key
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using WalkingTec.Mvvm.Core;

namespace ERCS.Model
{
    public class Report : TopBasePoco
    {
        [Display(Name = "體溫")]
        [Required(ErrorMessage = "體溫是必填欄位")]
        [Range(30,50, ErrorMessage = "體溫必須是30到50度之間")]
        public float Temperature { get; set; }

        [Display(Name = "備註")]
        public string Remark { get; set; }

        [Display(Name = "患者名稱")]
        public Patient Patient { get; set; }
        //[Display(Name = "患者名稱")]
        //[Required(ErrorMessage = "患者名稱是必填欄位")]
        public int? PatientId { get; set; } //Foreign Key (GUID is overrided by integer)
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.DataAnnotations;
using WalkingTec.Mvvm.Core;

namespace ERCS.Model
{
    public enum VirusTypeEnum
    {
        DNA, RNA
    }
    public class Virus : TopBasePoco    // a record of the table
    {
        [Display(Name = "病毒名稱")]
        [Required(ErrorMessage = "病毒名稱是必填欄位")]
        public string VirusName { get; set; }   

        [Display(Name = "病毒編號")]
        [Required(ErrorMessage = "病毒編號是必填欄位")]
        [StringLength(10, ErrorMessage = "病毒編號最多10個字符")]    //not only validation, it also affect data field in database: varchar(10)
        public string VirusCode { get; set; }

        [Display(Name = "病毒描述")]
        public string Remark { get; set; }

        [Display(Name = "病毒種類")]
        [Required(ErrorMessage = "病毒種類是必填欄位")]
        public VirusTypeEnum? VirusType { get; set; } //Enum must have value by default

        // Many-to-Many relationship
        [Display(Name = "患者")]
        public List<PatientVirus> Patients { get; set; }
    }
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using System;
using System.Collections.Generic;
using System.Linq;
using WalkingTec.Mvvm.Core;
using ERCS.Model;

namespace ERCS.DataAccess
{
    public class DataContext : FrameworkContext
    {
        public DbSet<Location> Locations { get; set; } //database table
        public DbSet<ControlCenter> ControlCenters { get; set; } //database table
        public DbSet<Hospital> Hospitals { get; set; } //database table
        public DbSet<Patient> Patients { get; set; } //database table
        public DbSet<Report> Reports { get; set; } //database table
        public DbSet<Virus> Viruses { get; set; } //database table

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Patient>().HasKey(x => x.IdNumber); //**key** define index for IdNumber column in Patient table

            base.OnModelCreating(modelBuilder);
        }

        public DataContext(CS cs)
             : base(cs)
        {
        }
        public DataContext(string cs, DBTypeEnum dbtype)
            : base(cs, dbtype)
        {
        }
        public DataContext(string cs, DBTypeEnum dbtype, string version=null)
             : base(cs, dbtype, version)
        {
        }

    }

    /// <summary>
    /// DesignTimeFactory for EF Migration, use your full connection string,
    /// EF will find this class and use the connection defined here to run Add-Migration and Update-Database
    /// </summary>
    public class DataContextFactory : IDesignTimeDbContextFactory<DataContext>
    {
        public DataContext CreateDbContext(string[] args)
        {
            return new DataContext("your full connection string", DBTypeEnum.SqlServer);
        }
    }

}

查看更多

关注者
0
被浏览
258
刘亮
刘亮 2020-07-09
专业编码30年

我看了一下你的代码,

Cannot implicitly convert type '<System.Guid?>' to '<System.Guid>'
这个问题主要是代码生成器在处理中间表的时候默认认为你外键都是不为空的,后续我在修改一下代码生成器增加一下为空的判断,你在PatientVrius那个中间表里把VirusId设置为Guid就可以了

'PatientVirus' does not contain a definition for 'PatientIdNumber'
这个问题主要也是代码生成器并没有考虑到太特殊的情况,因为你在DataContext设置了:
modelBuilder.Entity<Patient>().HasKey(x => x.IdNumber); 这会导致所有关联Patient的外键的默认名字都变成了PatientIdNumber,而模型中并没有这个字段。 你可以手动修改一下生成的代码,把PatientIdNumber改成PatientId就可以了

1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览