我有一个两个模型,两个表有外键关系。我必须在单个请求中从两个表中获取记录。
模型结构如下: -
public partial class EmployeeRecord
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public tblEmployeeRecord()
{
this.countries = new HashSet<tblCountry>();
}
public int EmployeeId { get; set; }
public string Name { get; set; }
public string userName { get; set; }
public string userRole { get; set; }
public string id { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Country> countries { get; set; }
}
2.Country.cs
public partial class Country
{
public int CountryId { get; set; }
public int EmployeeId { get; set; }
public string CountryName { get; set; }
public virtual EmployeeRecord employeeRecord { get; set; }
}
public class EmployeeRecordsController : ApiController
{
private EstorageEntitiesforCombineView db = new EstorageEntitiesforCombineView();
// GET: api/EmployeeRecords
public IEnumerable<EmployeeRecord> GetEmployeeRecords([FromUri]PagingParameterModel pagingparametermodel)
{
var source= db.EmployeeRecords.OrderBy(a => a.EmployeeId);
// Get's No of Rows Count
if (pagingparametermodel.userRole == "HR")
{
source= (from a in db.EmployeeRecords
where a.userRole == "HR"
select a).OrderBy(a => a.EmployeeId);
}
else if(pagingparametermodel.userRole == "eStorage Admin")
{
source = (from a in db.EmployeeRecords
where a.userRole == "eStorage Admin"
select a).OrderBy(a => a.EmployeeId);
} else if(pagingparametermodel.userRole == "SharedService")
{
source = (from a in db.EmployeeRecords
where a.userRole == "SharedService"
select a).OrderBy(a => a.EmployeeId);
}
if(pagingparametermodel.toSearch == 1 && pagingparametermodel.userRole == "ALL")
{
source = (from b in db.EmployeeRecords
where b.Name.StartsWith(pagingparametermodel.name)
select b).OrderBy(a => a.EmployeeId);
}else if (pagingparametermodel.toSearch==1) {
source= (from b in db.EmployeeRecords
where b.Name.StartsWith(pagingparametermodel.name) && b.userRole==pagingparametermodel.userRole
select b).OrderBy(a => a.EmployeeId);
}
int count = source.Count();
// Parameter is passed from Query string if it is null then it default Value will be pageNumber:1
int CurrentPage = pagingparametermodel.pageNumber;
// Parameter is passed from Query string if it is null then it default Value will be pageSize:20
int PageSize = pagingparametermodel.pageSize;
// Display TotalCount to Records to User
int TotalCount = count;
// Calculating Totalpage by Dividing (No of Records / Pagesize)
int TotalPages = (int)Math.Ceiling(count / (double)PageSize);
// Returns List of Customer after applying Paging
var items = source.Skip((CurrentPage - 1) * PageSize).Take(PageSize).ToList();
// if CurrentPage is greater than 1 means it has previousPage
var previousPage = CurrentPage > 1 ? "Yes" : "No";
// if TotalPages is greater than CurrentPage means it has nextPage
var nextPage = CurrentPage < TotalPages ? "Yes" : "No";
// Object which we are going to send in header
var paginationMetadata = new
{
totalCount = TotalCount,
pageSize = PageSize,
currentPage = CurrentPage,
totalPages = TotalPages,
previousPage,
nextPage
};
// Setting Header
System.Web.HttpContext.Current.Response.Headers.Add("Paging-Headers", Newtonsoft.Json.JsonConvert.SerializeObject(paginationMetadata));
// Returing List of Customers Collections
return items;
}
}
我希望回复如下: -
[{
"tblCountries": [
{
"CountryId": 265,
"EmployeeId": 350,
"CountryName": "INWEST"
}
],
"EmployeeId": 350,
"Name": "ABC",
"userName": "[email protected]",
"userRole": "HR",
"id": nbh546652n45
}]
但回应如下: -
[{
"tblCountries": [],
"EmployeeId": 350,
"Name": "ABC",
"userName": "[email protected]",
"userRole": "HR",
"id": nbh546652n45
}]
我也试过,Include(a => a.countries)
如下: -
source= (from a in db.EmployeeRecords
where a.userRole == "HR"
select a).Include(a => a.countries).OrderBy(a => a.EmployeeId);
但我得到以下错误: -
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Object graph for type 'System.Collections.Generic.HashSet`1[[eStorageApi.Models.tblCountry, eStorageApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' contains cycles and cannot be serialized if reference tracking is disabled.
</ExceptionMessage>
<ExceptionType>
System.Runtime.Serialization.SerializationException
</ExceptionType>
尝试将这些LOC包含在webApiConfig.cs中: -
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling= Newtonsoft.Json.ReferenceLoopHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
仍然得到同样的错误。
在从api返回之前,将您的域模型投射到其他内容中。这样可以更好地控制响应数据格式,如果添加了属性(例如ssn),则不会无意中暴露它。这也有固定您的周期性参考的额外好处。
return items.Select(i => new {
i.Name,
i.Username,
...
Countries = i.Countries.Select(c => new {
c.CountryId,
c.CountryName,
...
}
};
您需要在employeeRecord和国家/地区之间建立关系。试试这个:
source= db.EmployeeRecords.Include(e => e.countries).Select(c => c.employeeRecord)
.Where(a => a.userRole == "HR");
当您执行请求时,您需要指定文本:Application / Json