dragon_cat dragon_cat - 3 months ago 9
C# Question

C# LINQ query creates unintended new row

I have the follow function that creates a new row or updates an existing row in model

MACReg
based on whether a given mac address exists.

public Boolean RegisterMAC(string pwd, string mac, string location)
{
School school = getSchoolByCode(pwd);
if (school == null)
{
return false;
}
//initial register or update
using (CloudPrintDbContext db = new CloudPrintDbContext())
{
MACReg r = db.MACRegs.Find(mac);
if (r == null) //create new row
{
MACReg m = new MACReg { MAC = mac, Location = location,
School = school, RegTime = DateTime.Now, UpdateTime = DateTime.Now };
db.MACRegs.Add(m);
}
else //update location
{
r.School = school;
r.Location = location;
r.UpdateTime = DateTime.Now;
}
db.SaveChanges();
}
return true;
}


However, the problem is that it always creates a new row in model
School
(not
MACReg
). Any idea why? Thanks!

Models for MACReg and School are below:

public class MACReg
{
[Key]
public string MAC { set; get; }

[Required]
public School School { set; get; }

[Required]
public string Location { set; get; }

[Required]
public DateTime UpdateTime { set; get; }

[Required]
public DateTime RegTime { set; get; }
}

public class School
{
[Key]
public int SchoolID { set; get; }

[Required]
public string SchoolName { set; get; }

[Required]
public DateTime CreateTime { set; get; }

[Required]
public DateTime PwdExprTime { set; get; }

[Required]
public byte[] PwdHash { set; get; }

[Required]
public byte[] Salt { set; get; }
}


UPDATE: getSchoolByCode is below

private School getSchoolByCode(string pwd)
{
using (CloudPrintDbContext db = new CloudPrintDbContext())
{
foreach(School s in db.Schools.Where(s => s.PwdExprTime > DateTime.Now)){
byte[] userH = HashUtils.GenerateHash_Salt(pwd, s.Salt);
if (HashUtils.CompareByteArrays(userH, s.PwdHash))
{
return s;
}
}
}
return null;
}

Answer

Your school is from a different CloudPrintDbContext so it's not tracked by the db instance in the using statement. If it isn't attached to any other DbContext then you could attach it to that one before you set the School and then it should work.

db.Schools.Attach(school);

As an aside I'd recommend you use the DbSet.Create() method instead of new so that you can use the dynamic proxies, as per EF documentation.