Asp.net mvc 在ASP.NET MVC中使用外键保存实体

Asp.net mvc 在ASP.NET MVC中使用外键保存实体,asp.net-mvc,entity-framework-ctp5,modelstate,Asp.net Mvc,Entity Framework Ctp5,Modelstate,我需要一些帮助做一些我认为很简单的事情。我正在使用ASP.net MVC 3和CodeFirst(CTP5) 我有两个实体:公司和地点。一家公司可以在多个地点运营。课程如下(去掉所有不必要的信息) 上市公司 { 公共int Id{get;set;} [必需] 公共字符串名称{get;set;} 公共虚拟ICollection位置{get;set;} } 公共类位置 { 公共int Id{get;set;} [必需] 公共字符串名称{get;set;} [必需] 公共虚拟公司公司{get;

我需要一些帮助做一些我认为很简单的事情。我正在使用ASP.net MVC 3和CodeFirst(CTP5)

我有两个实体:公司和地点。一家公司可以在多个地点运营。课程如下(去掉所有不必要的信息)

上市公司
{    
公共int Id{get;set;}
[必需]
公共字符串名称{get;set;}
公共虚拟ICollection位置{get;set;}
}
公共类位置
{
公共int Id{get;set;}
[必需]
公共字符串名称{get;set;}
[必需]
公共虚拟公司公司{get;set;}
}
现在在我的控制器中,我只允许在公司的上下文中创建一个位置,因此公司Id总是传入(在视图中,我在只读字段中显示公司名称,但不允许用户更改/编辑)

    public ActionResult Create(int companyId)
    {
        Company company = _session.Single<Company>(c => c.Id == companyId);
        Location newLocation = new Location {Company = company};
        return View(newLocation);
    } 

    [HttpPost]
    public ActionResult Create(Location location)
    {
        if (ModelState.IsValid)
        {
            _session.Add<Location>(location);
            _session.CommitChanges();                
            return RedirectToAction("Index");
        } else {
            return View(location);
        }
    }
public ActionResult创建(int companyId)
{
Company Company=\u session.Single(c=>c.Id==companyId);
地点newLocation=新地点{Company=Company};
返回视图(新位置);
} 
[HttpPost]
公共操作结果创建(位置)
{
if(ModelState.IsValid)
{
_增加(地点);
_session.CommitChanges();
返回操作(“索引”);
}否则{
返回视图(位置);
}
}

现在,每当我尝试创建一个新位置时,ModelState.IsValid总是false,因为没有提供location.Company.Name,并且它是Company上的必填字段。我从来没有尝试在这里创建一个新公司,我只是尝试创建一个引用了正确公司的位置。我不想将Name属性添加到视图只是为了验证模型状态。如何才能轻松完成?我应该传递与视图不同的内容吗?还是传递到视图?

您可以轻松地在
表单上添加一个隐藏字段,其中包含公司名。
。它的数据将按照预期被提取并发送到您的后期操作

如果您在服务器端根本不使用公司名称,只要公司ID正确(因为您使用它),就可以用任何虚拟文本填充此隐藏字段。但如果您确实需要使用正确的公司名称和ID,则必须将实际名称填充到隐藏字段中,而不是一些虚拟文本

无论如何。这将为您的公司名称添加一个隐藏字段

<%= Html.HiddenFor(m => m.Company.Name) %>
  • 使用继承:

    public class CompanyBase
    {
        public int Id { get; set; }
    }
    
    public class Company : CompanyBase
    {
        [Required]
        public string Name { get; set; }
    
        public virtual ICollection<Location> Locations { get; set; }
    }
    
    public class Location
    {
        public int Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public virtual CompanyBase Company { get; set; }
    
    }
    
    公共类公司数据库
    {
    公共int Id{get;set;}
    }
    公共类公司:CompanyBase
    {
    [必需]
    公共字符串名称{get;set;}
    公共虚拟ICollection位置{get;set;}
    }
    公共类位置
    {
    公共int Id{get;set;}
    [必需]
    公共字符串名称{get;set;}
    [必需]
    公共虚拟公司基础公司{get;set;}
    }
    

  • 正如我在评论中解释的那样,我偶然发现了一个小小的改变,这使得这项工作得以进行,但我仍然认为这是一个难题,因为我不明白为什么我需要复制child Id paramater,但我能找到的最好/最简单的一个应该在将来很容易更新,我将第一个承认我不知道所有(或大部分)关于CodeFirst中的内容

    我将location类更改为:

    public class Location  
    {      
        public int Id { get; set; }        
    
        [Required]      
        public string Name { get; set; }        
    
        [Required]      
        public virtual Company Company { get; set; }    
    }
    
    致:

    现在据我所知,这根本没有改变数据库模式,但是现在位置上唯一需要做的事情(验证时)是CompanyId字段中有一个ID,Company属性可以保留为null(之前,它试图验证一个正确的公司,因为Company类是必需的)

    因此,现在在创建位置时,视图只需在CompanyId中传回


    有人看到创建(位置)函数的缺点吗?或者更好的方法吗?

    Location.CompanyID有值集吗?可能需要定义public int CompanyID{get;set;}是的,设置了公司Id(保存时查看ModelState证明了这一点。显示的唯一错误是公司上需要的名称字段。我仍然认为这是一个难题,但它工作得很好,如果我能找到更好的方法,应该很容易更改。基本上我做了两件事。请参阅下面的aas帖子。)我没有足够的空间在评论中放置htis)谢谢,是的,我想到了这一点,但是现在我只有两个必填字段,因为我正在为我的站点设置很多脚手架,但是每次我向我的公司实体添加一个新的必填字段,我都需要回来编辑Location Create方法/视图。似乎应该有某种方法来分离这两个字段,因为我真的需要是id。@Robert Koritnik-nice插件,但值得一提的是ASP.NET MVC 3默认包含JSON模型绑定(JsonValueProviderFactory)@Peter:检查我编辑过的答案。根据您的应用程序模型实体及其使用情况,场景2可能会有点麻烦和复杂。@RPM1984:没错,但它不是默认添加的。您必须在全局中手动添加它。谢谢Robert,我回家后会看更多:).当我说我的模型将要改变时,我的意思是当我改变公司模型时(添加新字段,其中一些字段是必需的),这对创建位置应该没有影响,因为位置应该关心的是Id。如果我添加了一个必填地址字段,那么显然我必须更新公司视图,但我希望能够不使用位置视图和控制器:)。再次感谢您提供的信息,我将研究一下您的方法,看看是否可以采用:)这对我来说很好,还有一个[SkipePrequestValidation]选项,您可以使用它谢谢Devo。“我也会调查一下的。”彼得-在我看来并不是一个混球;这似乎是最有效的解决办法。我已经花了一天左右的时间
    public class LocationCreate
    {
        public int Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public int CompanyId { get; set; }
    
        public Location ToModelInstance()
        {
            return new Location {
                Id = this.Id,
                Name = this.Name,
                Company = new Company {
                    Id = this.CompanyId,
                    Name = "Super duper company Ltd." // you can as well omit this line
                }
            };
        }
    }
    
    public class CompanyBase
    {
        public int Id { get; set; }
    }
    
    public class Company : CompanyBase
    {
        [Required]
        public string Name { get; set; }
    
        public virtual ICollection<Location> Locations { get; set; }
    }
    
    public class Location
    {
        public int Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public virtual CompanyBase Company { get; set; }
    
    }
    
    public class Location  
    {      
        public int Id { get; set; }        
    
        [Required]      
        public string Name { get; set; }        
    
        [Required]      
        public virtual Company Company { get; set; }    
    }
    
    public class Location  
    {      
        public int Id { get; set; }        
    
        [Required]      
        public string Name { get; set; }        
    
        [Required]      
        public int CompanyId { get; set; }
        public virtual Company Company { get; set; }    
    }