Я увидел что-то странное, с той точки зрения, что я не ожидал этого.
Давайте возьмем этот простой код, чтобы вы могли увидеть, что я сделал:
MyRepository db = new MyRepository();
// let's get them all
IQueryable<TblCals> cals = db.FindAllCalendars();
// now that we have everything, let's split up
List<TblCals> masters = cals.Where(x => x.IsMaster).ToList();
List<TblCals> childs = cals.Where(x => x.Parent > 0).ToList();
// Let's change the name of the masters
foreach(var c in masters) c.Name = String.Concat("Master: ", c.Name);
// Let's send everything to the View
return View(new model() { masters, childs });
Теперь проблема :
Почему имя, изменяющееся в List
masters
, также меняет имя объектов, находящихся в childs
?
Когда я делаю List<TblCals> masters = cals.Where(x => x.IsMaster).ToList();
, не должно ли это скопировать элементы вместо того, чтобы ссылаться на них только из объекта cals
?
Что я могу сделать , чтобы предотвратить это поведение?
Я мог бы просто сделать:
MyRepository db = new MyRepository();
// let's get them all
IQueryable<TblCals> cals = db.FindAllCalendars();
// now that we have everything, let's split up
List<TblCals> masters = db.FindAllCalendarsThatAreMasters().ToList();
List<TblCals> childs = db.FindAllCalendarsThatHaveParent().ToList();
но в итоге получится 3 запроса к базе данных , и я мог бы просто сначала получить все, а затем использовать этот объект ... но не в том случае, если "главный" объект продолжает изменяться, когда я меняю любой подзапрос из него.
Основная идея, стоящая за всем этим, состоит в том, чтобы убедиться, что это безопасно:
public IEnumerable<JK_Users> ListAllUsers() {
// Check / Add to memcache
string key = "ListAllUsers";
var users = MemcachedLayer.Get<IEnumerable<JK_Users>>(key);
if(key == null)
users = db.Tbl_Users.CachedQuery(key);
return users;
}
public IEnumerable<JK_Users> FindUserById(decimal id) {
// call ListAllUsers() instead Repository
return this.ListAllUsers().FirstOrDefault(x => x.user_id == id);
}
public IEnumerable<JK_Users> FindUserByUsername(string username) {
// call ListAllUsers() instead Repository
return this.ListAllUsers().FirstOrDefault(x => x.username == username);
}
или мне нужно позвонить
public JK_Users FindUserById(decimal id) {
return db.Tbl_Users.FirstOrDefault(x => x.user_id == id);
}
public JK_Users FindUserByUsername(string username) {
return db.Tbl_Users.FirstOrDefault(x => x.username == username);
}
Так что я могу использовать кэш более эффективно.