2016-08-17 4 views
0

Я не совсем уверен, что то, что я хочу, возможно или нет, вот что я хочу:Сохранение объектов в качестве ссылок?

У меня есть пара коллекций различных объектов, которые я храню. Скажем, коллекция Users и коллекция Projects.

Вот некоторые примеры того, что они могли бы выглядеть следующим образом:

public class User 
{ 
    public int UserId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string EmailAddress { get; set; } 

    public List<Project> Projects { get; set;} 
} 

public class Project 
{ 
    public int ProjectId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 

    public User Manager { get; set; } 
} 

Как вы можете видеть, пользователь может иметь несколько проектов, в то время как проект имеет пользователь.

В основном, когда у меня есть эти данные, я хочу иметь возможность редактировать пользователя в коллекции пользователей и автоматически обновлять любые проекты с этим пользователем, чтобы содержать обновленную информацию об этом пользователе. Впоследствии, если я обновляю проект, у Пользователей с этим Проектом будет автоматически обновлен их Проект. Как какой-то способ хранения ссылок на объекты, а не на значения?

Есть ли способ сделать это?

+5

Ключевое слово звучит как «магазин». Что вы имеете в виду? 'Project' и' User' являются ссылочными типами, поэтому экземпляры 'Project' в' Projects' и 'User', на которые ссылается' Manager', уже являются ссылками. –

+0

Вы пробовали, чтобы узнать, что произойдет? Я думаю, вы заметите, что он уже делает именно то, что вы хотите. –

+0

Это уже произойдет. –

ответ

3

У вас есть объекты ссылки. Это означает, что до тех пор, пока вы ссылаетесь на тот же объект (экземпляр), по умолчанию все работает так, как вы ожидали.

Пример (используя классы):

User u = new User(); 
Project p = new Project(); 
p.Manager = u; 
u.Projects.Add(p); 

Это создает пустой пользователя и пустой проект. Проект ссылается на пользователя, список проектов пользователя ссылается на проект.

Теперь вы измените имя пользователя и проект:

u.FirstName = "Test"; 
u.LastName = "User"; 

Это позволит вам получить следующий результат:

Console.WriteLine("{0} {1}", p.Manager.FirstName, p.Manager.LastName); 
=> Test User 

Другая вещь, которую вы можете сделать сейчас, заключается в следующем:

User userInfo = p.Manager; 
userInfo.EMailAddress = "[email protected]"; 

Это будет отражать любой способ доступа к объекту пользователя, который вы назначили, поскольку все эти «переменные» «указывая» на один и тот же экземпляр объекта (они ссылаются на один и тот же объект в памяти).

Вы можете даже передать свой объектную ссылку на другой метод:

public void ChangeProjectManagerEmail(Project theProject, string newEMail) 
{ 
    theProject.Manager.EMailAddress = newEMail; 
} 

Вызов выше метод, как это:

ChangeProjectManagerEmail(p, "[email protected]"); 

приведет к следующим образом:

Console.WriteLine(u.EMailAddress); 
=> [email protected] 

Что не работает:

User anotherUser = new User(); 
anotherUser.UserId = 5; 

Console.WriteLine(p.Manager.UserId); 

Этот выход будет 0, как новый пользователь anotherUser не ссылается на какой-либо другой объект.

Вам нужно быть осторожным, когда дело доходит до сохранения такой структуры. Хотя хранить его (в файле, базе данных и т. Д.) Довольно просто, вам нужно убедиться, что вы заново создаете ту же самую структуру объекта, когда читает данных. Представьте себе:

  • Проект 1 ссылки u1 Пользователь
  • Project 2 ссылки u1 Пользователь
  • ссылки u1 проекта 1 и 2

Теперь в первую очередь вы должны решить, хотите ли вы упорствовать на пользователя или на проект, иначе вы можете выполнять дублируемую работу. Когда восстанавливает сохраненную информацию, вам необходимо убедиться, что вы создали только один пользователь! (лучше всего использовать уникальный идентификатор, чтобы проверить, был ли пользователь уже восстановлен). В противном случае вы получите два разных объекта User с той же информацией, и вам будет интересно, почему изменение пользователя отражает только один проект. Наихудший случай заключается в том, что после изменения пользовательской информации у вас будет два пользователя с одинаковым идентификатором, но с другой информацией в вашем хранилище.


Все, что сказал: WATCH OUT! Структура вашего объекта несколько опасна с точки зрения перекрестных ссылок. Как и сейчас, очень удобно добавлять проект к пользователю, который ссылается на совершенно другого пользователя в качестве своего менеджера. Пример:

User user1 = new User(); 
// Initialize ID, name, etc. 

User user2 = new User(); 
// Initialize ID, name, etc. 

Project p = new Project(); 
// Initialize stuff 
p.Manager = user2; 

user1.Projects.Add(p); 

См. Неполадку здесь?

+0

Downvoter: позаботиться о комментариях? –

0

Вы можете реализовать шаблон проектирования наблюдателя, чтобы уведомить «наблюдателей», когда изменяется конкретный объект.

«Шаблон проектирования наблюдателя требует разделения между наблюдателем, который регистрируется для уведомлений, и поставщиком, который контролирует данные и отправляет уведомления одному или нескольким наблюдателям».

См реализации этой модели в Dot Net:

https://msdn.microsoft.com/en-us/library/ff506346(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/ee817669.aspx

Если вы хотите, чтобы только на уровне базы данных, вы можете создать триггер "ON UPDATE", чтобы сделать желаемые изменения.

+0

Я не уверен, помогает ли это, потому что я думаю, что базовые знания об объектных ссылках отсутствует –

+0

Okay @Thorsten Dittmar, это правда ... Во всяком случае, он и все люди, которые получают доступ, могут получить знания ... – Alvimar

0

Почему бы вам не только сохранить идентификатор пользователя в проекте, и когда вам требуется знать, кто этот проект принадлежит только запустить select как users.select(x => x.userid == project.userid)

+0

И почему бы не сохранить список проектов для каждого пользователя? –

+0

@ThorstenDittmar Ну, он это делает или вы саркастичны? Я не понимаю – Neil

+0

Нет, я не саркастичен. Я просто немного неправильно понял ваш ответ :-) Я хотел сказать, что было бы лучше решить, хотите ли вы, чтобы каждый проект ссылался на пользователя он принадлежит ** или ** каждый пользователь хранит список всех его проектов, но не обоих, так как это может привести к проблемам (см. мой ответ внизу). Мой комментарий, направленный на sayin g, что либо решение имеет больше накладных расходов, если вы хотите определить другой компонент. –

Смежные вопросы