为什么在使用通过支持MVC 5 / EF 6(继承)派生类创建的视图和控制器时会收到错误?
我的背景:我是以前的Powerbuilder(客户端/服务器程序员),正在努力学习基于Web的编程。 我选择了ASP.NET并购买了MSDN许可证以使用Visual Studio 2013,并且已经通过书籍,在线培训和计算机上的旧版黑客进行学习。 最好的测试是创建一些示例应用程序,所以我在这里。我正在学习MVC和Code First EF,因为有很多好的信息和样本。 但是,我仍然坚持我的继承示例。
我有3个类:AircrewMember派生自Airman派生自Person。他们编译没有错误。 我有一个类DbInitializer所以“Code First”将创建数据库。我实际上使用SQL脚本来加载我的测试数据。 我有一个类StanEvalDb用于数据库上下文信息。 我已经从web.config中包含了相关信息。
问题:
当我使用scaffolding创建一个控制器和基于Airman类(派生自Person)的视图时,结果会返回错误。
Airman airman = db.People.Find(id);
错误1
无法将类型'SEMX1.Entities.Person'隐式转换为'SEMX1.Entities.Airman'。存在显式转换(您是否错过了演员?)
D:\ Projects \ VC2013 \ 2015 \ 06-Jun \ SEMX1 \ SEMX1.Web \ Controllers \ AirmenController.cs 31 29 SEMX1.Web
我想我理解每个层次结构表(TPH),并且实际上只创建了一个表(People)来容纳所有“3”表。
我不知所措......我用Google搜索并阅读了很多文章,但我不知道如何继续。有没有人看过这个或尝试过这个?
我认为我忽视了一些简单的事情,但我没有想法。任何帮助将不胜感激!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SEMX1.Entities
{
public class Person
{
public virtual int PersonId { get; set; }
[DisplayName("First Name* ")]
[StringLength(40)]
[Required(ErrorMessage = "The First Name field is required.")]
public virtual string PersonFirstName { get; set; }
[DisplayName("Middle Initial ")]
[StringLength(2)]
public virtual string PersonMidInit { get; set; }
[DisplayName("Last Name* ")]
[StringLength(50)]
[Required(ErrorMessage = "The Last Name field is required.")]
public virtual string PersonLastName { get; set; }
[DisplayName("SSN* ")]
[StringLength(11)]
[Required(ErrorMessage = "The SSN field is required.")]
public virtual string PersonSSN { get; set; }
[DisplayName("DOB* ")]
[Required(ErrorMessage = "The DOB field is required.")]
public virtual DateTime? PersonDOB { get; set; }
public virtual int CivilRankId { get; set; }
//public virtual int LifeEventId { get; set; }
public virtual ICollection<LifeEvent> LifeEvents { get; set; }
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SEMX1.Entities
{
public class Airman : Person
{
public virtual int MilitaryRankId { get; set; }
public virtual int MilitaryUnitId { get; set; }
public virtual int AfscId { get; set; }
public virtual ICollection<CareerEvent> CareerEvents { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SEMX1.Entities
{
public class AircrewMember : Airman
{
public virtual int AviationTypeId { get; set; }
public virtual int AirMissionId { get; set; }
public virtual int AircraftId { get; set; }
public virtual int CrewPositionId { get; set; }
public virtual int ExperienceRatingId { get; set; }
public virtual int AirmanshipId { get; set; }
public virtual int TacticalDayRatingId { get; set; }
public virtual int TacticalNightRatingId { get; set; }
public virtual ICollection<AircrewEvent> AircrewEvents { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using SEMX1.Entities;
using System.IO;
namespace SEMX1.Web.DataContexts
{
public class DbInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<StanEvalDb>
{
protected override void Seed(StanEvalDb context)
{
base.Seed(context);
// using SQL scripts to load database with test data
// easier way to get around identity key field problems
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using SEMX1.Entities;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace SEMX1.Web.DataContexts
{
public class StanEvalDb : DbContext
{
public StanEvalDb() : base("StanEvalContext")
{
Database.SetInitializer<StanEvalDb>(new DbInitializer());
}
public DbSet<Person> People { get; set; }
public DbSet<LifeEvent> LifeEvents { get; set; }
public DbSet<CivilRank> CivilRanks { get; set; }
public DbSet<MilitaryRank> MilitaryRanks { get; set; }
public DbSet<MilitaryUnit> MilitaryUnits { get; set; }
public DbSet<MilUnitType> MilUnitTypes { get; set; }
public DbSet<AFSC> AFSCList { get; set; }
public DbSet<CareerEvent> CareerEvents { get; set; }
public DbSet<Airman> Airmen { get; set; }
public DbSet<AviationType> AviationTypes { get; set; }
public DbSet<AirMission> AirMissions { get; set; }
public DbSet<Aircraft> AircraftList { get; set; }
public DbSet<CrewPosition> CrewPositions { get; set; }
public DbSet<ExperienceRating> ExperienceRatings { get; set; }
public DbSet<Airmanship> AirmanshipList { get; set; }
public DbSet<TacticalDayRating> TacticalDayRatings { get; set; }
public DbSet<TacticalNightRating> TacticalNightRatings { get; set; }
public DbSet<AircrewEvent> AircrewEvents { get; set; }
public DbSet<AircrewMember> Aircrew { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//modelBuilder.Entity<Person>()
// .HasMany(p => p.LifeEvents).WithMany(l => l.People)
// .Map(t => t.MapLeftKey("PersonID")
// .MapRightKey("LifeEventID")
// .ToTable("LifeEventPersons"));
//modelBuilder.Entity<Airman>()
// .HasMany(a => a.CareerEvents).WithMany(c => c.Airmen)
// .Map(t => t.MapLeftKey("PersonID")
// .MapRightKey("CareerEventID")
// .ToTable("CareerEventAirmen"));
//modelBuilder.Entity<AircrewMember>()
// .HasMany(a => a.AircrewEvents).WithMany(c => c.Aircrew)
// .Map(t => t.MapLeftKey("PersonID")
// .MapRightKey("AircrewEventID")
// .ToTable("AircrewEventAircrew"));
}
}
}
Web.config (Pertinent Information)
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</configSections>
<connectionStrings>
<add name="StanEvalContext"
connectionString="Data Source=REDCARBOSS2-LAP\RCB2SRV2012;Initial Catalog=DB_25213_SEMX1;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False"
providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient"
type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using SEMX1.Entities;
using SEMX1.Web.DataContexts;
namespace SEMX1.Web.Controllers
{
public class AirmenController : Controller
{
private StanEvalDb db = new StanEvalDb();
// GET: Airmen
public ActionResult Index()
{
return View(db.People.ToList());
}
// GET: Airmen/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Airman airman = db.People.Find(id);
if (airman == null)
{
return HttpNotFound();
}
return View(airman);
}
// GET: Airmen/Create
public ActionResult Create()
{
return View();
}
// POST: Airmen/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PersonId,PersonFirstName,PersonMidInit,PersonLastName,PersonSSN,PersonDOB,CivilRankId,MilitaryRankId,MilitaryUnitId,AfscId")] Airman airman)
{
if (ModelState.IsValid)
{
db.People.Add(airman);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(airman);
}
// GET: Airmen/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Airman airman = db.People.Find(id);
if (airman == null)
{
return HttpNotFound();
}
return View(airman);
}
// POST: Airmen/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "PersonId,PersonFirstName,PersonMidInit,PersonLastName,PersonSSN,PersonDOB,CivilRankId,MilitaryRankId,MilitaryUnitId,AfscId")] Airman airman)
{
if (ModelState.IsValid)
{
db.Entry(airman).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(airman);
}
// GET: Airmen/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Airman airman = db.People.Find(id);
if (airman == null)
{
return HttpNotFound();
}
return View(airman);
}
// POST: Airmen/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Airman airman = db.People.Find(id);
db.People.Remove(airman);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
答案 0 :(得分:0)
错误说它无法隐式转换并要求您显式转换。尝试替换它:
Airman airman = db.People.Find(id);
使用:
Airman airman = (Airman)db.People.Find(id);