使用EntityFramework传入非PK值获取PK值
Get PK value by passing in non-PK value using EntityFramework
我正在构建一个 Windows Phone 8.1 应用程序,它使用 Web API 和 Entity Framework 连接到 SQL 数据库。使用我当前的设置,我的服务项目中的实体(包含 PK id 属性)和 phone 客户端项目中的模型(不包含 PK id 属性 为了在创建新成员时启用自动递增。我正在尝试编写一个服务方法,当用户名传递给它时,returns memberID 值(成员实体的 PK)。但是,当我这样做时,出现以下错误:
System.InvalidCastException: 无法将类型 'System.Net.Http.StreamContent' 的对象转换为类型 'System.IConvertible'.
我不确定我是否正在尝试做一些不起作用的事情,或者是否有更简单的方法来做到这一点,但我的代码构建成功。上面的错误是 运行 次错误。这是我用于相关 类:
的代码
这是从客户端后端调用我的服务器的方法:
public async void GetMembers(String currUser, String currPass)
{
using (var client = new HttpClient())
{
//MembersListBox.Items.Add("using block entered");
client.BaseAddress = new Uri("http://nflff.azurewebsites.net");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//MembersListBox.Items.Add("client's defaultrequestheaders done");
//gets all members from table
HttpResponseMessage response = await client.GetAsync("api/Members");
//MembersListBox.Items.Add("after response reached");
if (response.IsSuccessStatusCode)
{
//reads all member objs from table as a json string
string s = await response.Content.ReadAsStringAsync();
//how can we pass the user's login credentials (including ID) to other pages? via HttpClient?
//converts string of members into a list of member objs
var deserializedResponse = JsonConvert.DeserializeObject<List<Members>>(s);
foreach (Members member in deserializedResponse)
{
//if current member matches a member found in list
if(member.compareUserAndPassword(currUser, currPass)) {
MembersListBox.Items.Add(currUser + " and " + currPass + " found.");
MembersListBox.Items.Add(member.userName + " " + member.password);
Members currMember = member; //this works
MembersListBox.Items.Add("Current member: " + currMember.ToString());
//how should memberID be remembered for user?
client.DefaultRequestHeaders.Authorization = CreateBasicHeader(currUser, currPass);
MembersListBox.Items.Add(client.DefaultRequestHeaders.Authorization);
HttpResponseMessage memResponse = await client.GetAsync("api/Members/" + currUser);
if (memResponse.IsSuccessStatusCode)
{
MembersListBox.Items.Add("memResponse successful");
}
//should only go to home page if successful
//int memID = Convert.ToInt32(await client.GetAsync("api/Members?MemberStr=" + currUser));
HttpResponseMessage thisMember = await client.GetAsync("api/Members?MemberStr=" + currUser);
var con = thisMember.Content;
var head = thisMember.Headers;
var rm = thisMember.RequestMessage;
int memID = Convert.ToInt32(thisMember.Content);//THIS IS THE LINE THAT GENERATES THE ERROR
//will need to call server's getidbyname method and pass result instead of currMember.memberID
//this.Frame.Navigate(typeof(HomeHub), currMember.memberID);
this.Frame.Navigate(typeof(HomeHub), memID);
}
}
}
//MembersListBox.Items.Add(Members.MembersList.Count);
foreach (var member in Members.MembersList)
{
// MembersListBox.Items.Add(member.ToString());
}
}
}
这是我的服务项目中的控制器:
public class MembersController : ApiController
{
private GatoradeShowerDB db = new GatoradeShowerDB();
// GET: api/Members
public IQueryable<Member> GetMembers()
{
return db.Members;
}
// GET: api/Members/5
[ResponseType(typeof(Member))]
public async Task<IHttpActionResult> GetMember(int id)
{
Member member = await db.Members.FindAsync(id);
if (member == null)
{
return NotFound();
}
return Ok(member);
}
//GET: api/Members?MemberStr={memberStr}
[ResponseType(typeof(Member))]
public async Task<T> GetMemberIDByName<T>(String MemberStr) where T : struct
{
//var member = JsonConvert.DeserializeObject<Member>(MemberStr);
//Member member = await db.Members.FindAsync(MemberStr);
//var userId = ...;
var member = await db.Members.Where(x => x.UserName == MemberStr).ToListAsync();
if (member == null)
{
return (T)Convert.ChangeType(NotFound(), typeof(T));
}
return (T)Convert.ChangeType(member[0].MemberID, typeof(T));
//return member[0].MemberID; //hopefully gets id of first member in async list and returns it
//return Ok(member);
}
//other methods
}
此外,这是我的客户端模型:
public class Members
{
//[JsonProperty("MemberID")]
//public int memberID { get; private set; }
[JsonProperty("FirstName")]
private string firstName { get; set; }
[JsonProperty("LastName")]
private string lastName { get; set; } //both names should be optional
[JsonProperty("UserName")]
public string userName { get; private set; } //note: I don't think we should track first and last names
[JsonProperty("Password")]
public string password { get; private set; } //will probably need to implement validation in setter so won't be able to auto-implement
[JsonProperty("Email")]
private string email { get; set; }//same with this. will need validation
[JsonProperty("MemberCity")]
private string memberCity { get; set; }
[JsonProperty("MemberState")]
private string memberState { get; set; }
[JsonProperty("MemberZip")]
private string memberZip { get; set; }
[JsonProperty("MemberPhone")]
private string memberPhone { get; set; }//should also be optional
[JsonProperty("FaveTeamID")]
private int faveTeamID { get; set; }
public static List<Members> MembersList = new List<Members>();
public Members(string first, string last, string user, string pass, string email, string city, string state, string zip, string phone, int team)
{
//memberID = id;
firstName = first;
lastName = last;
userName = user;
password = pass;
this.email = email;
memberCity = city;
memberState = state;
memberZip = zip;
memberPhone = phone;
faveTeamID = team;
}
public override string ToString()
{
return "Member: " + userName + " in " + memberCity;
}
public bool compareUserAndPassword(string currUser, string currPass)
{
if (currUser.Equals(userName) && currPass.Equals(password))
{
return true;
}
else
{
return false;
}
}
}
最后,这是我的服务器端数据对象:
public partial class Member
{
public int MemberID { get; set; }
[Required]
[StringLength(255)]
public string FirstName { get; set; }
[Required]
[StringLength(255)]
public string LastName { get; set; }
[Required]
[StringLength(50)]
public string UserName { get; set; }
[Required]
[StringLength(32)]
public string Password { get; set; }
[Required]
[StringLength(50)]
public string Email { get; set; }
[Required]
[StringLength(50)]
public string City { get; set; }
[Required]
[StringLength(30)]
public string State { get; set; }
[Required]
[StringLength(255)]
public string Zip { get; set; }
[Required]
[StringLength(255)]
public string Phone { get; set; }
public int FavTeamID { get; set; }
}
我知道这是很多代码,但我宁愿 post 太多而不是太少。我曾想过以某种方式将 MemberID 值添加到 httpClient 对象并将其作为参数传递给其他页面,但我不确定这是否可行。如果特定成员的 MemberID 值仅存储在服务器端数据对象中而不存储在客户端模型中,我如何获取该值?如果有更简单的方法来解决这个问题,我也愿意接受不同的方法。预先感谢您的帮助。
更新
我的问题似乎源于控制器中的 GetMemberIDByName 方法。当我调试它时,我收到以下错误消息:
无法在控制器 'WorkingVersionGetItDone.Controllers.MembersController' 上调用操作方法 'System.Threading.Tasks.Task`1[T] GetMemberIDByNameT',因为该操作方法是通用方法。
我很确定你的方法应该更像这样:
public async Task<IHttpActionResult> GetMemberIDByName(string MemberStr)
{
var member = await db.Members.Where(x => x.UserName == MemberStr).ToListAsync();
if (member == null)
{
return NotFound();
}
return Ok(member[0].MemberID);
}
然后调用者将得到一个 404(NotFound()
)或一个 200,有效负载为 MemberID
,您可以适当地处理。
HttpResponseMessage memberResponse = await client.GetAsync("api/Members?MemberStr=" + currUser);
if(memberResponse.StatusCode == HttpStatusCode.OK)
{
// got the memberId...
var memberId = Convert.ToInt32( memberResponse.Content.ReadAsStringAsync().Result);
}
else if(memberResponse.StatusCode == HttpStatusCode.NotFound)
{
// member not found...
}
我正在构建一个 Windows Phone 8.1 应用程序,它使用 Web API 和 Entity Framework 连接到 SQL 数据库。使用我当前的设置,我的服务项目中的实体(包含 PK id 属性)和 phone 客户端项目中的模型(不包含 PK id 属性 为了在创建新成员时启用自动递增。我正在尝试编写一个服务方法,当用户名传递给它时,returns memberID 值(成员实体的 PK)。但是,当我这样做时,出现以下错误:
System.InvalidCastException: 无法将类型 'System.Net.Http.StreamContent' 的对象转换为类型 'System.IConvertible'.
我不确定我是否正在尝试做一些不起作用的事情,或者是否有更简单的方法来做到这一点,但我的代码构建成功。上面的错误是 运行 次错误。这是我用于相关 类:
的代码这是从客户端后端调用我的服务器的方法:
public async void GetMembers(String currUser, String currPass)
{
using (var client = new HttpClient())
{
//MembersListBox.Items.Add("using block entered");
client.BaseAddress = new Uri("http://nflff.azurewebsites.net");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//MembersListBox.Items.Add("client's defaultrequestheaders done");
//gets all members from table
HttpResponseMessage response = await client.GetAsync("api/Members");
//MembersListBox.Items.Add("after response reached");
if (response.IsSuccessStatusCode)
{
//reads all member objs from table as a json string
string s = await response.Content.ReadAsStringAsync();
//how can we pass the user's login credentials (including ID) to other pages? via HttpClient?
//converts string of members into a list of member objs
var deserializedResponse = JsonConvert.DeserializeObject<List<Members>>(s);
foreach (Members member in deserializedResponse)
{
//if current member matches a member found in list
if(member.compareUserAndPassword(currUser, currPass)) {
MembersListBox.Items.Add(currUser + " and " + currPass + " found.");
MembersListBox.Items.Add(member.userName + " " + member.password);
Members currMember = member; //this works
MembersListBox.Items.Add("Current member: " + currMember.ToString());
//how should memberID be remembered for user?
client.DefaultRequestHeaders.Authorization = CreateBasicHeader(currUser, currPass);
MembersListBox.Items.Add(client.DefaultRequestHeaders.Authorization);
HttpResponseMessage memResponse = await client.GetAsync("api/Members/" + currUser);
if (memResponse.IsSuccessStatusCode)
{
MembersListBox.Items.Add("memResponse successful");
}
//should only go to home page if successful
//int memID = Convert.ToInt32(await client.GetAsync("api/Members?MemberStr=" + currUser));
HttpResponseMessage thisMember = await client.GetAsync("api/Members?MemberStr=" + currUser);
var con = thisMember.Content;
var head = thisMember.Headers;
var rm = thisMember.RequestMessage;
int memID = Convert.ToInt32(thisMember.Content);//THIS IS THE LINE THAT GENERATES THE ERROR
//will need to call server's getidbyname method and pass result instead of currMember.memberID
//this.Frame.Navigate(typeof(HomeHub), currMember.memberID);
this.Frame.Navigate(typeof(HomeHub), memID);
}
}
}
//MembersListBox.Items.Add(Members.MembersList.Count);
foreach (var member in Members.MembersList)
{
// MembersListBox.Items.Add(member.ToString());
}
}
}
这是我的服务项目中的控制器:
public class MembersController : ApiController
{
private GatoradeShowerDB db = new GatoradeShowerDB();
// GET: api/Members
public IQueryable<Member> GetMembers()
{
return db.Members;
}
// GET: api/Members/5
[ResponseType(typeof(Member))]
public async Task<IHttpActionResult> GetMember(int id)
{
Member member = await db.Members.FindAsync(id);
if (member == null)
{
return NotFound();
}
return Ok(member);
}
//GET: api/Members?MemberStr={memberStr}
[ResponseType(typeof(Member))]
public async Task<T> GetMemberIDByName<T>(String MemberStr) where T : struct
{
//var member = JsonConvert.DeserializeObject<Member>(MemberStr);
//Member member = await db.Members.FindAsync(MemberStr);
//var userId = ...;
var member = await db.Members.Where(x => x.UserName == MemberStr).ToListAsync();
if (member == null)
{
return (T)Convert.ChangeType(NotFound(), typeof(T));
}
return (T)Convert.ChangeType(member[0].MemberID, typeof(T));
//return member[0].MemberID; //hopefully gets id of first member in async list and returns it
//return Ok(member);
}
//other methods
}
此外,这是我的客户端模型:
public class Members
{
//[JsonProperty("MemberID")]
//public int memberID { get; private set; }
[JsonProperty("FirstName")]
private string firstName { get; set; }
[JsonProperty("LastName")]
private string lastName { get; set; } //both names should be optional
[JsonProperty("UserName")]
public string userName { get; private set; } //note: I don't think we should track first and last names
[JsonProperty("Password")]
public string password { get; private set; } //will probably need to implement validation in setter so won't be able to auto-implement
[JsonProperty("Email")]
private string email { get; set; }//same with this. will need validation
[JsonProperty("MemberCity")]
private string memberCity { get; set; }
[JsonProperty("MemberState")]
private string memberState { get; set; }
[JsonProperty("MemberZip")]
private string memberZip { get; set; }
[JsonProperty("MemberPhone")]
private string memberPhone { get; set; }//should also be optional
[JsonProperty("FaveTeamID")]
private int faveTeamID { get; set; }
public static List<Members> MembersList = new List<Members>();
public Members(string first, string last, string user, string pass, string email, string city, string state, string zip, string phone, int team)
{
//memberID = id;
firstName = first;
lastName = last;
userName = user;
password = pass;
this.email = email;
memberCity = city;
memberState = state;
memberZip = zip;
memberPhone = phone;
faveTeamID = team;
}
public override string ToString()
{
return "Member: " + userName + " in " + memberCity;
}
public bool compareUserAndPassword(string currUser, string currPass)
{
if (currUser.Equals(userName) && currPass.Equals(password))
{
return true;
}
else
{
return false;
}
}
}
最后,这是我的服务器端数据对象:
public partial class Member
{
public int MemberID { get; set; }
[Required]
[StringLength(255)]
public string FirstName { get; set; }
[Required]
[StringLength(255)]
public string LastName { get; set; }
[Required]
[StringLength(50)]
public string UserName { get; set; }
[Required]
[StringLength(32)]
public string Password { get; set; }
[Required]
[StringLength(50)]
public string Email { get; set; }
[Required]
[StringLength(50)]
public string City { get; set; }
[Required]
[StringLength(30)]
public string State { get; set; }
[Required]
[StringLength(255)]
public string Zip { get; set; }
[Required]
[StringLength(255)]
public string Phone { get; set; }
public int FavTeamID { get; set; }
}
我知道这是很多代码,但我宁愿 post 太多而不是太少。我曾想过以某种方式将 MemberID 值添加到 httpClient 对象并将其作为参数传递给其他页面,但我不确定这是否可行。如果特定成员的 MemberID 值仅存储在服务器端数据对象中而不存储在客户端模型中,我如何获取该值?如果有更简单的方法来解决这个问题,我也愿意接受不同的方法。预先感谢您的帮助。
更新
我的问题似乎源于控制器中的 GetMemberIDByName 方法。当我调试它时,我收到以下错误消息:
无法在控制器 'WorkingVersionGetItDone.Controllers.MembersController' 上调用操作方法 'System.Threading.Tasks.Task`1[T] GetMemberIDByNameT',因为该操作方法是通用方法。
我很确定你的方法应该更像这样:
public async Task<IHttpActionResult> GetMemberIDByName(string MemberStr)
{
var member = await db.Members.Where(x => x.UserName == MemberStr).ToListAsync();
if (member == null)
{
return NotFound();
}
return Ok(member[0].MemberID);
}
然后调用者将得到一个 404(NotFound()
)或一个 200,有效负载为 MemberID
,您可以适当地处理。
HttpResponseMessage memberResponse = await client.GetAsync("api/Members?MemberStr=" + currUser);
if(memberResponse.StatusCode == HttpStatusCode.OK)
{
// got the memberId...
var memberId = Convert.ToInt32( memberResponse.Content.ReadAsStringAsync().Result);
}
else if(memberResponse.StatusCode == HttpStatusCode.NotFound)
{
// member not found...
}