#c# #ef-code-first #oop #object-oriented-database
#c# #ef-code-first #ооп #объектно-ориентированная база данных
Вопрос:
Сначала я пытаюсь смоделировать своего рода отношения «множественного наследования» с кодом EF 4.1. Вот пример того, что я пытаюсь сделать.
Допустим, я пытаюсь смоделировать способ взаимодействия пользователя с моим приложением с использованием объекта «User». Это, будучи базовым классом, используется для описания текущего пользователя, когда он ничего конкретного не делает (например, посещает домашнюю страницу). Это может выглядеть так:
public class User
{
public Guid ID { get; set; } // Just use the forms authentication user ID
public string FirstName { get; set; }
public string LastName { get; set; }
}
Теперь, если я хочу создать представление того же пользователя, но в другой части сайта, скажем, как покупателя, это может выглядеть следующим образом:
public class Shopper : User
{
public virtual ICollection<Orders> Orders { get; set; }
}
И так далее, и тому подобное. Когда я захожу вставить Shopper, у которого есть ранее существовавшая запись пользователя, он выдает исключение, потому что PK уже взят в пользовательской таблице.
Есть ли какой-либо способ сначала смоделировать эту (IsA) взаимосвязь с EF-кодом? Или я собираюсь застрять с чем-то подобным?
public class Shopper
{
public Guid UserID { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public string FirstName
{
get { return User.FirstName; }
set { User.FirstName = value; }
}
// yada, yada, yada...
}
Я хотел бы сначала придерживаться кода и моделировать отношения прямо в моем DbContext, но я не могу понять, как сделать что-то подобное. Спасибо!
Редактировать:
Итак, я пытаюсь сделать что-то вроде этого:
public void SomeMethod ()
{
var UserID = Guid.NewGuid ();
var MyUser = new User () { ID = UserID };
SaveUserToDatabase (MyUser);
var ShopperRepresentation = GetUserAsShopper (UserID);
// Do stuff.
}
В основном, как использование объектно-ориентированных ролей, я думаю. Я хочу использовать один и тот же PK для каждого представления этого пользователя, но хранить всю их базовую информацию в базовом классе под названием User. Я знаю, что это возможно, если я, конечно, напишу свой собственный SQL, но я хочу посмотреть, сможет ли EF Code First сделать это тоже.
Ответ №1:
Да, вы можете сделать это так, как вы описали в своих первых двух примерах кода.
Я думаю, вам просто нужно определить сопоставление, которое вы захотите выполнить в своей OnModelCreating
функции DataContext
в дополнение к правильной настройке ваших классов. Как вы это делаете, зависит от того, какую схему отображения вы используете. Я выбрал Table-Per-Type (TPT) в моем последнем проекте, поэтому у меня было что-то вроде этого:
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<Shopper>().ToTable("Shoppers");
modelBuilder.Entity<OtherUser>().ToTable("OtherUsers");
Дайте мне знать, если у вас это не сработает, и я посмотрю, что я могу сделать.
Редактировать:
Увидев ваше разъяснение ниже, я не могу придумать, как это сделать. Вам пришлось бы хранить каждый объект отдельно (поскольку EF рассматривает покупателя просто как покупателя, а не как покупателя и пользователя), даже если они используют общие данные. Это может привести к несоответствиям данных (если, скажем, покупатель обновил свою фамилию, а пользователь — нет). Я думаю, вам было бы лучше использовать что-то вроде:
public class User
{
public virtual Guid ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual ShopperInfo { get; set; }
}
public class ShopperInfo
{
public virtual ICollection<Order> Orders { get; set; }
}
и затем, когда вам нужно рассматривать пользователя как покупателя, вы просто получаете доступ к ShopperInfo (и если его там нет, вы его создаете). EF без проблем сможет правильно настроить это для вас.
Хотя, если у вас будет много типов пользователей, это может стать громоздким. Хотя просто предложение — я думаю, что это немного чище.
Комментарии:
1. @Tim — спасибо за ваш ответ! Я могу создавать таблицы просто отлично. Что я пытаюсь сделать, так это создать пользователя и вставить его. Затем, позже, используйте того же пользователя, например, в качестве покупателя. PK — это идентификатор пользователя, указанный при проверке подлинности в формах. Итак, в зависимости от того, что делает пользователь, у них будет другой объект, представляющий их. Итак, пользовательский объект не будет содержать ничего об их опыте покупок, но их клиентская версия будет.
2. Из того, что вы там сказали … вы создаете экземпляры пользовательского объекта… а затем иногда также создается экземпляр Shopper?
3. @Tim — да, в зависимости от того, какую страницу они посещают. Это тот же «человек», использующий тот же PK, но другое представление о том, что они делают / что они могут сделать.
4. Хорошо, исходя из этого, я отредактировал свою рекомендацию. не уверен, что вам это понравится. Но я не знаю, как идти дальше в том направлении, в котором вы ищете.
5. @Tim — в ответ на вашу правку я испугался, что именно это мне придется сделать. Я подумал, что стоит потратить время на поиск SO и посмотреть, есть ли у кого-нибудь еще другое мнение. Я подожду, есть ли у кого-нибудь еще мнение, и, если ничего лучшего не всплывет, дам вам ответ. Спасибо за ваше время!