powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / c# фабрика классов EF Code First
17 сообщений из 17, страница 1 из 1
c# фабрика классов EF Code First
    #38796929
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.

Подскажите пожалуйста, как правильно реализовать фабрику классов в EF.

Описание доменной структуры EF Code First:

Имеется класс Main, в котором реализована связь один ко многим к классам A B C.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class Main
{
     [Key]
     public int Id { get; set; }
     public string  Name { get; set; }

     // Связи с классами A B C  
     public virtual ICollection<A> As{ get; set; }
     public virtual ICollection<B> Bs{ get; set; }
     public virtual ICollection<С> Cs{ get; set; }

     // Нужно реализовать в одном методе ли свойстве вывод набора данных As, Bs, Cs
     // public Fabric_A_B_C 
 
}


Классы с ForeingKey
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
public class A
{   
     [Key] 
     public int Id { get; set; }
     public string Name { get; set; }

     public int IdMain { get; set; } // Foreing Key
     public Main Main { get; set; }
}
public class B
{   
     [Key] 
     public int Id { get; set; }
     public string Adress{ get; set; }

     public int IdMain { get; set; } // Foreing Key
     public Main Main { get; set; }
}
public class C
{   
     [Key] 
     public int Id { get; set; }
     public bool Status { get; set; }

     public int IdMain { get; set; } // Foreing Key
     public Main Main { get; set; }
}



Теперь собственно говоря сам вопрос.
Как реализовать вывод свойств ICollection (As, Bs, Cs) класса Main, через один общий метод или свойство?

Нормально объяснил?
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38797155
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
нет... вопрос и задача неясны... приведенный пример наводит на печальные мысли... фабрика как-то выбивается из примера(задачи)...
абстрактный класс интерфейс...? почитать про наследование(inheritance) в (with) EF [Code First]?...
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38801885
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Почитал как вы говорили про наследования. Но вопрос все равно остался.

Постараюсь еще раз объяснить суть задачи, со стороны интерфейса.

Имеется два DataGridView:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
 - Первый DataGridView, он же основной. Выводит к примеру каталог разных запчастей на автомобиль. 
                                        Структура полей в данном таблице общая для всех типов запчастей.
                                        (Артикул( Primery Key ), Название).
                                        ItemSourse = привязка к классу Main.
                                         
 - Второй DataGridView вспомогательный. Он предназначен для вывода подробной информации исходя из выбранной позиции в первом DataGridView.
                                        Наборы данных, которые выводятся в DataGridView:
                                        объявлены в классе Main
                                        public virtual ICollection<A> As{ get; set; }
                                        public virtual ICollection<B> Bs{ get; set; }
                                        public virtual ICollection<С> Cs{ get; set; }
                                        
                                        В итоге, чтобы отображалась информация во втором DataGridView, нужно биндить к ItemSourse одну из ICollection (As или Bs или Cs). 
                                        Что не позволяет, мне в DataGridView выводить информацию по любому ICollection, не выполнив
                                        очередной бинд к ItemSourse.
   

Задача, которую я пытаюсь решить заключается: как при помощи одного биндинга , выводить информацию во второй DataGridView, любой из трех ICollection?
ItemSourse = " As_Bs_Cs "
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38801898
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nechto,

А как понять что выводить во второго гриде: все А, все B, или все С? На основе чего такой вывод делается? Ведь в каждой записи Main есть все три коллекции?
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38801941
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVosttNechto,
А как понять что выводить во второго гриде: все А, все B, или все С?

Любая запись в Main, может имеет только одну из трех коллекций, остальные две будут пустые.
К примеру:

Код: plaintext
1.
2.
3.
4.
5.
ID   NAME   As   Bs    Cs

1    1111   null  {B}  null
2    2222   {A}  null  null
3    3333   {A}  null  null


hVosttNechto,
На основе чего такой вывод делается? Ведь в каждой записи Main есть все три коллекции?

Вот мне и надо сделать своего рода объединяющее свойство которое бы выводила коллекции в таком виде:
Код: plaintext
1.
2.
3.
4.
5.
ID   NAME   As_Bs_Cs

1    1111   {B}  
2    2222   {A}
3    3333   {A}
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38801976
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nechto,

А, тогда можно (и скорее всего даже нужно) реализовать это следующим образом:

1. Вместо одного Main класса, базовый MainBase и три наследника MainA, MainB, MainC
2. Каждый из наследников ссылается только на 1 свою коллекцию: As, Bs, Cs.
3. Берёшь из базы коллекцию MainBase и суёшь в первый грид.
4. Биндишь второй грид на вычисляемое свойство-коллекцию.

Пример:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
public abstract class Main
{
     [Key]
     public int Id { get; set; }
     public string  Name { get; set; } 

     public abstract ICollection<object> Foreigns { get; }
}

public class MainA : Main
{
     public virtual ICollection<A> As{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return As.Cast<object>(); }
     }
}

public class MainB : Main
{
     public virtual ICollection<B> Bs{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return Bs.Cast<object>(); }
     }
}

public class MainC : Main
{
     public virtual ICollection<С> Cs{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return Cs.Cast<object>(); }
     }
}




Классы с ForeingKey


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
public class A
{   
     [Key] 
     public int Id { get; set; }
     public string Name { get; set; }

     public int IdMain { get; set; } // Foreing Key
     public MainA Main { get; set; }
}
public class B
{   
     [Key] 
     public int Id { get; set; }
     public string Adress{ get; set; }

     public int IdMain { get; set; } // Foreing Key
     public MainB Main { get; set; }
}
public class C
{   
     [Key] 
     public int Id { get; set; }
     public bool Status { get; set; }

     public int IdMain { get; set; } // Foreing Key
     public MainC Main { get; set; }
}



Маппишь второй грид к свойству Foregns.

Я без понятия что ты собрался выводить, и главное КАК, если A,B,C -- разные классы с разными набором свойств, так что и вывел object, может делать ToString хотябы. Незнаю в общем. Но суть такая.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38802143
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может я что-то не понял.

Но при такой реализации, у меня теперь три Main для первого DataGridView. А нужен то один.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38802182
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtoМожет я что-то не понял.

Но при такой реализации, у меня теперь три Main для первого DataGridView. А нужен то один.

Нет, один Main и три его наследника. Из EF получаешь Main:

Код: c#
1.
2.
3.
var mains = context.Mains.ToList();

// работаешь с mains, там лежат экземпляры-наследники: MainA, MainB, MainC



Добавляешь в базу конкретные Main:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
using(var context = new MyContext())
{
 
   var ma = new MainA { ... };
   context.Mains.Add(ma);

   var mb = new MainB { ... };
   context.Mains.Add(mb);

   ...
  
}



В общем, это самое простое решение. Кроме того, исходя из твоей задачи, что каждый Main должен содержать лишь одну из трёх коллекций, это самый очевидно правильный способ решения, так как технически не допускает ошибки, и ты точно знаешь, что у тебя за Main (A,B или C).
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38802194
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А этот пример, который вы привели выше, будет работать с Code First?
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38802209
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtoА этот пример, который вы привели выше, будет работать с Code First?

Именно.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38802934
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за помощь, сейчас буду пробовать.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38803078
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Что то не выходи.

Делаю миграцию
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
public partial class dsdsd : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.A",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        Adress = c.String(maxLength: 100),
                        IdMain = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.Katalog", t => t.IdMain, cascadeDelete: true)
                .Index(t => t.IdMain);
				
			CreateTable(
                "dbo.B",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        Name = c.String(maxLength: 100),
                        IdMain = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.Katalog", t => t.IdMain, cascadeDelete: true)
                .Index(t => t.IdMain);	
				
			CreateTable(
                "dbo.C",
                c => new
                    {
                        Id = c.Int(nullable: false, identity: true),
                        Status = c.Boolean(),
                        IdMain = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.Katalog", t => t.IdMain, cascadeDelete: true)
                .Index(t => t.IdMain);	
            
            CreateTable(
                "dbo.Katalog",
                c => new
                    {
                        UnionId = c.Int(nullable: false, identity: true),
                        Name = c.String(maxLength: 200),
                        Discriminator = c.String(nullable: false, maxLength: 128), // Откуда взялось это поле???
                    })
                .PrimaryKey(t => t.UnionId)
        }		
	}	




По этой структуре

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
public abstract class Main
{
     [Key]
     public int Id { get; set; }
     public string  Name { get; set; } 

     public abstract ICollection<object> Foreigns { get; }
}

public class MainA : Main
{
     public virtual ICollection<A> As{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return As.Cast<object>().ToList(); }
     }
}

public class MainB : Main
{
     public virtual ICollection<B> Bs{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return Bs.Cast<object>().ToList(); }
     }
}

public class MainC : Main
{
     public virtual ICollection<С> Cs{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return Cs.Cast<object>().ToList(); }
     }
}




Почему-то генерируется это поле Discriminator.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38803160
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtoПочему-то генерируется это поле Discriminator.

Всё верно, с помощью этого поля EF определяет что там MainA, MainB или MainC. Техническое поле, оно необходимо.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38803306
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Выходит что без этого поля не обойтись, я правильно понимаю.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38803442
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NechtoВыходит что без этого поля не обойтись, я правильно понимаю.

Без дополнительного поля нет. EF с помощью этого поля реализует наследование. Тебе-то какая разница? Ну добавилось поле, от этого ни жарко, ни холодно. Зато задача решена.

Если есть сильное желание, можно изменить тип и название этого поля, но обычно это нафиг не нужно.
...
Рейтинг: 0 / 0
c# фабрика классов EF Code First
    #38803516
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hVosttNechtoВыходит что без этого поля не обойтись, я правильно понимаю.

Без дополнительного поля нет. EF с помощью этого поля реализует наследование. Тебе-то какая разница? Ну добавилось поле, от этого ни жарко, ни холодно. Зато задача решена.

Если есть сильное желание, можно изменить тип и название этого поля, но обычно это нафиг не нужно.

НУ так то оно так. Спасибо за грамотное решения задачи.

Вот еще поделюсь своим первым вариантом, который я сделал до открытия этой темы. Так для полноты темы.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
public class Main
{
     [Key]
     public int Id { get; set; }
     public string  Name { get; set; }

     // Связи с классами A B C  
     public virtual ICollection<A> As{ get; set; }
     public virtual ICollection<B> Bs{ get; set; }
     public virtual ICollection<С> Cs{ get; set; }

     // Мое первое решение
     [NotMapped]
     public virtual ICollection<object> Foreigns
     {
          get 
          {
               object out = null;
               if (As.Any()) out = As.Cast<object>().ToList(); 
               else if (Bs.Any()) out = Bs.Cast<object>().ToList(); 
               else if (Cs.Any()) out = Cs.Cast<object>().ToList();

               return out;
          }
     }   
 
}
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
c# фабрика классов EF Code First
    #39255418
Nechto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возобновлю тему, появился вопрос.
Использую данный пример в моем приложении.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
public abstract class Main
{
     [Key]
     public int Id { get; set; }
     public string  Name { get; set; } 

     public abstract ICollection<object> Foreigns { get; }
}

public class MainA : Main
{
     public virtual ICollection<A> As{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return As.Cast<object>().ToList(); }
     }
}

public class MainB : Main
{
     public virtual ICollection<B> Bs{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return Bs.Cast<object>().ToList(); }
     }
}

public class MainC : Main
{
     public virtual ICollection<С> Cs{ get; set; }

     public override ICollection<object> Foreigns 
    { 
         get { return Cs.Cast<object>().ToList(); }
     }
}



Подскажите пожалуйста, почему при запросе на прямую Main , у меня Foreigns пустой?
Код: c#
1.
var query = contextDb.Set<Main>().ToList();



Не пустой он только в том случае, если использовать метод Load()
Код: c#
1.
2.
3.
4.
contextDb.Set<A>().Load();
contextDb.Set<B>().Load();
contextDb.Set<C>().Load();
var query = contextDb.Set<Main>().ToList();



Почему так? Ведь там есть служебное поле Discriminator.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / c# фабрика классов EF Code First
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]