【问题标题】:How do I create a code first model that references another model twice in C# MVC?如何在 C# MVC 中创建引用另一个模型两次的代码优先模型?
【发布时间】:2013-01-18 10:35:52
【问题描述】:

我试图了解如何使用代码优先方法来做到这一点。当我过去使用 SQL 语句和 ASP 编写更多代码时,我了解如何做到这一点。现在我正在尝试用 C# 中的代码优先 MVC 方法自学如何理解它。

首先,如果我要在 SQL 中解释我想要的内容,我希望重现类似的内容。

    Select s1.systemname, s2.systemname, j,jumplaneid 
    from systems s1, systems s2, jumplanes j 
    where s1.systemid = j.system1id and s2.systemid = j.system2id

这是我的系统模型。

    public class system
    {
    public virtual int systemid { get; set; }
    public virtual string systemname { get; set; }
    public virtual int? posx { get; set; }
    public virtual int? posy { get; set; }
    public virtual int? starluminosityid { get; set; }
    public virtual int? stellartypeid { get; set; }
    public virtual int? starspectralclassid { get; set; }
    public virtual int? carry { get; set; }
    public virtual int? raw { get; set; }
    public virtual int? bio { get; set; }
    public virtual int? jumppoints { get; set; }
    public virtual int? specialrolls { get; set; }

    public virtual ICollection<settlement> settlements { get; set; }
    public virtual ICollection<fleet> fleets { get; set; }
    public virtual ICollection<Jumplane> jumplanes { get; set; }
    public virtual stellartype Stellartype { get; set; }
    public virtual starluminosity Luminosity { get; set; }
    public virtual starspectralclass SpectralClass { get; set; }
}

我正在尝试创建一个可以引用端点系统模型的跳线模型。我是这样设置的,我认为它很接近,但并不完全在那里。想法?

public class Jumplane
{
    public virtual int jumplaneid { get; set; }
    public virtual int jumpcost { get; set; }
    public virtual string jumplanename { get; set; }
    public virtual system system1 { get; set; }
    public virtual system system2 { get; set; }
    public virtual ICollection<Supplyline> supplylines { get; set; }
}

当我执行“更新数据库”以在数据库中设置所有内容时,我得到如下所示的跟踪:

    PM> update-database -force
    Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
    No pending code-based migrations.
    Applying automatic migration: 201302030335260_AutomaticMigration.
    System.Data.SqlClient.SqlException (0x80131904): Either the parameter @objname is     ambiguous or the claimed @objtype (COLUMN) is wrong.
      at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
      at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
      at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
      at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
      at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout)
      at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
      at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
      at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
      at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
      at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
      at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
      at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading, Boolean auto)
      at System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
      at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
      at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
      at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
      at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
      at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
      at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
      at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
    ClientConnectionId:c4c1ba62-806b-4e68-bb0b-161da4d9e23e
    Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong.

如果我先设置数据库,我知道该怎么做,但我正在尝试学习代码优先方法。任何更熟悉软件开发当前趋势的人能够指导我吗?

谢谢!

更新:谢谢你们,从你们每个人身上学到了一些东西。

这就是我结束的地方。

    public class Jumplane
{
    [Key]
    public int jumplaneid { get; set; }      
    [Range (1,1000)]
    public decimal jumpcost { get; set; }
    [Required]
    [StringLength(30)]
    public string jumplanename { get; set; }
    public virtual Starsystem starsystem1 { get; set; }
    public virtual Starsystem starsystem2 { get; set; }
    public virtual ICollection<Supplyline> supplylines { get; set; }
}

和

public class Starsystem
{
    [Key]
    public int starsystemid { get; set; }
    public string systemname { get; set; }
    public int? posx { get; set; }
    public int? posy { get; set; }
    public int? starluminosityid { get; set; }
    public int? stellartypeid { get; set; }
    public int? starspectralclassid { get; set; }
    public int? carry { get; set; }
    public int? raw { get; set; }
    public int? bio { get; set; }
    public int? jumppoints { get; set; }
    public int? specialrolls { get; set; }

    public virtual ICollection<settlement> settlements { get; set; }
    public virtual ICollection<fleet> fleets { get; set; }
    public virtual ICollection<Jumplane> jumplanes { get; set; }
    public virtual stellartype Stellartype { get; set; }
    public virtual starluminosity Luminosity { get; set; }
    public virtual starspectralclass SpectralClass { get; set; }
}

我将返回并捕获其他注释。因为我的头已经消失并且被尖尖的头发覆盖,所以我错过了注释的意义。

当您建议它是重命名问题时,我遇到的更新数据库问题变得很清楚。添加 -Verbose 选项让我非常清楚。我可能作弊了,但我通过删除其中的两个星系统引用来简化模型,更新数据库,然后将它们一一添加回来。

我也很欣赏关于类大写和使用“virtual”关键字的代码审查。我确实在 id 和 name 上留下了更具描述性的前缀,但这主要是为了我,因为如果我不使用它们,我以后可能会感到困惑。由于代码只适合我,我决定传递那条特别的建议,但反馈是(并且仍然是)最受欢迎的。

再次感谢你们的时间和专业知识。

【问题讨论】:

    标签: c# asp.net-mvc entity-framework code-first


    【解决方案1】:

    此错误通常在您尝试重命名表时产生。

    我建议您创建模型并尝试以最少的可能字段实现您想要的结果。此外,您只想在外国实体上使用 virtual 关键字。

    我刚刚测试了类似的东西(Admin, AdminLog[Contains Admin1 and Admin2]),它工作得很好。

    你应该尝试的代码

    public class System
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
    
    public class Jumplane
    {
        public int ID { get; set; }
        public virtual System System1 { get; set; }
        public virtual System System2 { get; set; }
    }
    

    现在此代码可以运行,您将能够执行所需的 LINQ 查询,只需向其中添加所有其他字段。

    一些指针(可能是主观的)

    • 仅限外国虚拟
    • 类以大写字母开头
    • 不需要SystemID、SystemName 字段,只需ID 和Name 即可,因为您会看到它属于System

    【讨论】:

      【解决方案2】:

      在 EF 中您想要的查询类似于 dbContext.Jumplanes.Include("system1").Include("system2")

      话虽如此,您的模型没有属性/注释,一切都是虚拟的。当您希望延迟加载属性时,只需将其设置为虚拟属性。元素的主键不应该真正延迟加载。

      看看Key 和ForeignKey 属性,用这些注释你的模型,删除不需要的虚拟关键字,然后告诉我们它是怎么回事:)

      【讨论】:

        猜你喜欢
        • 2014-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多