2014-01-20 35 views
1

我有一个具有多个导航属性的类控制器:EntitySetController多个导航性能

public partial class Fixture 
{ 
    public int FixtureId { get; set; } 

    //foreign key 
    public int StageId { get; set; } 
    //navigation properties 
    public virtual Stage Stage { get; set; } 

    //foreign key 
    public int CityId { get; set; } 
    //navigation properties 
    public virtual City City { get; set; } 

    public DateTime FixtureDate { get; set; } 

    //foreign key 
    public int AwayTeamId { get; set; } 
    //navigation properties 
    public virtual Team AwayTeam { get; set; } 

    //foreign key 
    public int HomeTeamId { get; set; } 
    //navigation properties 
    public virtual Team HomeTeam { get; set; } 

    public byte? AwayTeamScore { get; set; } 
    public byte? HomeTeamScore { get; set; } 
} 

我现在写我的第一EntitySetController和我想包括3种导航性能。我知道如何包括像这样的:

public IQueryable<Fixture> GetFixtures() 
{ 
    return db.Fixtures.Include("Stage"); 
} 

是否可以包含多个这些导航属性?

另外,在我的帖子中,我如何使用这些获取相关对象?在之前的版本中,我编写了一个ApiController版本库方法来获取它们(见下文)。什么是EntitySetController等值?

public override HttpResponseMessage Post(Fixture fixture) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      Stage stage = _repository.GetStageByStageId(fixture.StageId); 
      City city = _repository.GetCityByCityId(fixture.CityId); 
      Team awayTeam = _repository.GetTeamByTeamName(fixture.AwayTeamName); 
      Team homeTeam = _repository.GetTeamByTeamName(fixture.HomeTeamName); 

      Fixture entity = new Fixture(); 
      entity.StageId = stage.StageId; 
      entity.CityId = city.CityId; 
      entity.FixtureDate = fixture.FixtureDate; 
      entity.AwayTeamId = awayTeam.TeamId; 
      entity.HomeTeamId = homeTeam.TeamId; 
      entity.AwayTeamScore = fixture.AwayTeamScore; 
      entity.HomeTeamScore = fixture.HomeTeamScore; 

      db.Fixtures.Add(fixture); 
      db.SaveChanges(); 
      var response = Request.CreateResponse(HttpStatusCode.Created, fixture); 
      //response.Headers.Location = new Uri(Url.Link("DefaultApi", 
      //        new { id = fixture.FixtureId })); 

      return response; 
     } 
     else 
     { 
      return Request.CreateResponse(HttpStatusCode.BadRequest); 
     } 
    } 
    catch 
    { 
     return Request.CreateResponse(HttpStatusCode.BadRequest); 
    } 
} 

编辑:我已经使用了多种包括和引用的中邮方法导航性能:

public override HttpResponseMessage Post(Fixture fixture) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      Fixture entity = new Fixture(); 
      entity.StageId = fixture.Stage.StageId; 
      entity.CityId = fixture.City.CityId; 
      entity.FixtureDate = fixture.FixtureDate; 
      entity.AwayTeamId = fixture.AwayTeam.TeamId; 
      entity.HomeTeamId = fixture.HomeTeam.TeamId; 
      entity.AwayTeamScore = fixture.AwayTeamScore; 
      entity.HomeTeamScore = fixture.HomeTeamScore; 

      db.Fixtures.Add(entity); 
      db.SaveChanges(); 
      var response = Request.CreateResponse(HttpStatusCode.Created, fixture); 

      return response; 
     } 
     else 
     { 
      return Request.CreateResponse(HttpStatusCode.BadRequest); 
     } 
    } 
    catch 
    { 
     return Request.CreateResponse(HttpStatusCode.BadRequest); 
    } 
} 

但我得到一个400错误请求的错误,当我考虑对象通过它看起来这样

request: Object 
body: "{"FixtureId":0,"StageId":0,"CityId":0,"FixtureDate":"2014-09-08T21:00:00.000","AwayTeamId":0,"HomeTeamId":0}" 
callbackParameterName: "$callback" 
data: Object 
AwayTeam: undefined 
AwayTeamId: 0 
AwayTeamScore: undefined 
City: undefined 
CityId: 0 
FixtureDate: "2014-09-08T21:00:00.000" 
FixtureId: 0 
HomeTeam: undefined 
HomeTeamId: 0 
HomeTeamScore: undefined 
Stage: undefined 
StageId: 0 

的UI看起来是这样的,所有的下拉菜单成功填充:

<div data-ng-app="app" ng-controller="FixtureAddController"> 
    <form name="form" class="col-xs-2" id="form" class="form-horizontal"> 
     <div class="control-group" ng-class="{error: form.StageName.$invalid}"> 
      <label class="control-label" for="StageName">Stage Team</label> 
      <div class="controls"> 
       <select class="form-control" ng-model="fixture.StageName" ng-options="stage.StageName as stage.StageName for stage in stages" required> 
        <option style="display:none" value="">Select</option> 
       </select> 
       <span ng-show="form.StageName.$dirty && form.StageName.$error.required">Stage required</span> 
      </div> 
     </div> 
     <div class="control-group" ng-class="{error: form.CityName.$invalid}"> 
      <label class="control-label" for="CityName">City</label> 
      <div class="controls"> 
       <select class="form-control" ng-model="fixture.CityName" ng-options="city.CityName as city.CityName for city in cities" required> 
        <option style="display:none" value="">Select</option> 
       </select> 
       <span ng-show="form.CityName.$dirty && form.CityName.$error.required">City required</span> 
      </div> 
     </div> 
     <div class="control-group" ng-class="{error: form.FixtureDate.$invalid}"> 
      <label class="control-label" for="BirthDate">Fixture Date</label> 
      <div class="controls"> 
       <input type='text' class="form-control" ng-model='fixture.FixtureDate' name='FixtureDate' title="FixtureDate" ng-pattern='/^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/' required /> 
       <span ng-show='form.FixtureDate.$dirty && form.FixtureDate.$error.required'>Fixture Date required</span> 
       <span ng-show='form.FixtureDate.$dirty && form.FixtureDate.$error.pattern'>Fixture Date invalid</span> 
      </div> 
     </div> 
     <div class="control-group" ng-class="{error: form.HomeTeamName.$invalid}"> 
      <label class="control-label" for="HomeTeamName">Home Team</label> 
      <div class="controls"> 
       <select class="form-control" ng-model="fixture.HomeTeamName" ng-options="team.TeamName as team.TeamName for team in teams" required> 
        <option style="display:none" value="">Select</option> 
       </select> 
       <span ng-show="form.HomeTeamName.$dirty && form.HomeTeamName.$error.required">Home Team required</span> 
      </div> 
     </div> 
     <div class="control-group" ng-class="{error: form.AwayTeamName.$invalid}"> 
      <label class="control-label" for="AwayTeamName">Away Team</label> 
      <div class="controls"> 
       <select class="form-control" ng-model="fixture.AwayTeamName" ng-options="team.TeamName as team.TeamName for team in teams" required> 
        <option style="display:none" value="">Select</option> 
       </select> 
       <span ng-show="form.AwayTeamName.$dirty && form.AwayTeamName.$error.required">Away Team required</span> 
      </div> 
     </div> 
     <br /> 
     <div class="form-actions"> 
      <button ng-show="form.$valid" ng-click="save()" class="btn btn-primary">{{action}}</button> 
      <a href="/Admin/Fixtures/List" class="btn btn-danger">Cancel</a> 
     </div> 
    </form> 
</div> 

我该如何成功做到这个职位?

编辑2:当我在UI例如改变fixture.CityIdfixture.City.CityName的值在下拉绑定到固定的对象,当我发表我得到以下错误:

Exception {name: "HTTP request failed", message: "{"$id":"1","Message":"No HTTP resource was found t…http://lovelyjubbly.cloudapp.net/odata/$batch'."}", data: Object, stack: (...), _getStackTrace: function…} 
data: Object 
message: "HTTP request failed" 
request: Object 
body: " 
↵--batch_c20a-c604-4067 
↵Content-Type: multipart/mixed; boundary=changeset_3cce-3259-213d 
↵ 
↵--changeset_3cce-3259-213d 
↵Content-Type: application/http 
↵Content-Transfer-Encoding: binary 
↵ 
↵POST Cities HTTP/1.1 
↵Content-Id: 1 
↵MaxDataServiceVersion: 3.0 
↵DataServiceVersion: 3.0 
↵Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 
↵Content-Type: application/json;odata=verbose 
↵ 
↵{"CityId":0,"CityName":"Brasilia"} 
↵--changeset_3cce-3259-213d 
↵Content-Type: application/http 
↵Content-Transfer-Encoding: binary 
↵ 
↵POST Fixtures HTTP/1.1 
↵Content-Id: 2 
↵MaxDataServiceVersion: 3.0 
↵DataServiceVersion: 3.0 
↵Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1 
↵Content-Type: application/json;odata=verbose 
↵ 
↵{"FixtureId":0,"StageId":0,"CityId":0,"FixtureDate":"2012-11-10T22:00:00.000","AwayTeamId":0,"HomeTeamId":0,"City":{"__metadata":{"uri":"$1"}}} 
↵--changeset_3cce-3259-213d-- 
↵ 
↵--batch_c20a-c604-4067-- 
↵" 
callbackParameterName: "$callback" 
data: Object 
__batchRequests: Array[1] 
0: Object 
__changeRequests: Array[2] 
0: Object 
body: "{"CityId":0,"CityName":"Brasilia"}" 
data: Object 
headers: Object 
method: "POST" 
requestUri: "Cities" 
__proto__: Object 
1: Object 
body: "{"FixtureId":0,"StageId":0,"CityId":0,"FixtureDate":"2012-11-10T22:00:00.000","AwayTeamId":0,"HomeTeamId":0,"City":{"__metadata":{"uri":"$1"}}}" 
data: Object 
headers: Object 
method: "POST" 
requestUri: "Fixtures" 
__proto__: Object 
length: 2 

回答

0

第一个问题 - 是的,您可以包含多个导航属性。

return db.Fixtures 
    .Include("Stage") 
    .Include("FixtureDate") 
    .Include("AwayTeam"); 

编辑 关于你的第二个问题 - 如果已经定义了你Fixtures类具有的导航性能,并从数据库负载带回总图与所有相关“包括',那么在Controller> View> Controller流程之后,该模型应该仍然完好无损。 这意味着您应该能够访问像Fixture.AwayTeam.Name(或任何AwayTeam的属性可能看起来像)的数据。

您也可以将完整模型/图形的更改提交给EntityFramework,但是像这样的一个不连续的图表,您需要有一个策略,以便如何正确设置图表的每个部分的EntityState,否则可能会出错做事情时,如: - 提交采用现有AwayTeam新的灯具(EF将尝试创建一个新的AwayTeam,而不是现有的AwayTeam链接到新灯) - 提交编辑夹具和编辑AwayTeam

编辑2 对不起,刚才意识到我带来了EF,你的问题不是EF。忽略EF的细节!

+0

关于第二个问题,如果我想创建一个FixtureDTO,其中包括例如实际的StageName而不是外键的StageId,我可以在Post方法中使用Get/Fixture(5)/ Stage(如果是的话)会是语法),还是我会使用上面使用的类型的方法?另外,使用多个包含所有外键数据是否是一个好主意,这不会减慢执行速度吗? – user517406

+0

RE:使用多个包含的好主意。这真的取决于你的需求。是的,它会增加您的数据传输,因为您现在引入的不仅仅是基础实体。但是,如果你需要包含在包含内的信息,那么你需要把它带回来。 – Mashton

+0

请参阅上面的编辑 – user517406