none
Как привести 2 сущности с одинаковой структурой из разных ObjectContext к одному типу? RRS feed

  • Вопрос

  • Уважаемые Гуру!

    Допустим есть в разных базах данных таблицы - близнецы , с одинаковой структурой данных. Например, условно назовем ее  columnDescriptor (содержит описания полей - тип, длина, displayName и т.п.). В различных ObjectContext появятся сущности с одинаковой структурой, скажем в двух модулях

    roadControlModule.dbdescriptor 

    bridgeControlModule.dbdescriptor

    Автоматически сгенерированные сущности. 

    Как их привести к одному типу?

     

    • Изменено ATerentjev 25 декабря 2015 г. 12:39
    25 декабря 2015 г. 12:22

Ответы

  • Очень плохое решение, но можете попробовать.

    1. Объявите эту переменную для конкретного типа:

    dbdescriptor tds = (dbdescriptor)tdsEntityOfObjectType;

    2. Поиспользуйте ее в коде везде где вам надо.

    3. Поменяйте тип на

    dynamic tds = tdsEntityOfObjectType;

    4. Все будет работать для разных типов, но это все весьма опасно т.к. вместо проверки типов на этапе компиляции получаете проверку типов на этапе выполнения...

    • Помечено в качестве ответа ATerentjev 31 декабря 2015 г. 8:31
    29 декабря 2015 г. 7:09
    Отвечающий
  • Окончательно я сделал так.

    В SharedModule (Prism) , который используется в любом модуле создал класс

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SharedModule.Services
    {
        public class mfield
        {
            public int id { get; set; }              // ключ в базе данных
            public string m_name { get; set; }      // имя поля
            public string m_type { get; set; }       // тип 
            public int m_length { get; set; }        // длина
            public string m_group { get; set; }      // группа
            public string m_subgroup { get; set; }   // подгруппа
            public string m_table { get; set; }      // таблица
            public string m_display { get; set; }    // видимое имя
            public int m_order { get; set; }         // номер для упорядочивания
            public bool m_visible { get; set; }      // для управления видимостью
    
            public mfield() { 
            
            }
    
    
        }
    }

    А также интерфейс

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SharedModule.Services
    {
        public interface IRepository
        {
            List<mfield> fields();
        }
    }

    В реализации интерфейса 

        public class mobjectsRepository : IRepository
        {
            List<mfield> lmfields;
    
            public mobjectsRepository(dbcuksEntities dataContext)
            {
                lmfields = fields();
            }
            public List<mfield> fields() {
    
                return (from c in cuksContext.dbfields
                            where c.m_table == "mobject"
                            select
                             new mfield
                             {
                                 m_name = c.m_name,
                                 m_type = c.m_type,
                                 m_length = c.m_length,
                                 m_group = c.m_group,
                                 m_subgroup = c.m_subgroup,
                                 m_table = c.m_table,
                                 m_display = c.m_display,
                                 m_order = c.m_order,
                                 m_visible = c.m_visible
                             }).ToList<mfield>();
            }

    • Помечено в качестве ответа ATerentjev 31 декабря 2015 г. 9:54
    31 декабря 2015 г. 8:41

Все ответы

  • Добрый день.

    Не очень понимаю потребность... Но если у вас CodeFirst, попробуйте один класс подсунуть в два контекста.

    25 декабря 2015 г. 13:37
    Отвечающий
  • Возможно потребность связана с неправильным подходом где -то в другом месте. Попробую описать весь путь.

    1. Я сделал "табличный процессор" - т.е. программу, которая позволяет работать с сотнями таблиц. Стандартные операции редактирования , отчетов и т.п. Скрин я приведу. Для этого сделал 2 стандартных контрола -

    • типа PropertyGrid,
    •  DataGrid , соединенный с PropertyGrid через SelectedItem.

    В SelectedItem , masterView для dataGrid передаются наборы объектов типа Object, и все что нужно получаю через reflection и есть еще вспомогательная таблица dbDescriptor, каждая запись которой содержит описание какого-то поля для конкретной таблицы.

         Можно было бы использовать одну таблицу dbDescriptor для вообще всех рабочих таблиц, но мне показалось удобнее для каждого модуля (модуль для таблиц дорожных служб, модуль для таблиц МЧС) использовать свою таблицу dbDescriptor (Как говорил мой приятель - независимые вещи должны делаться независимо, хоть у них и одна структура).

         "Обертка" для ViewModel  (MVVM) общего DataGrid контрола содержит override функции, которые формируют masterView и dbDescriptors в виде коллекций типа objects. Но при работе с конкретными полями надо вытаскивать из dbDescriptors нужные записи. Я делаю это через reflection, т.к. типы dbDesriptor хоть и одинаковые, но напрямую с ними работать не получается, т.к. для компиллятора это разные сущности. 

          Я предположил, что есть способ сказать системе, что эти сущности эквивалентны в некотором смысле и можно воспользоваться выражениями типа

         
    dbdescriptor tds = (dbdescriptor)tdsEntityOfObjectType;

    И далее в запросах обращаться к полям tds напрямую

    tds.displayFieldName
    а не через reflection. Сейчас для получения коллекций использую виртуальные функции


            public virtual IEnumerable<object> getGridObjects() {
                if(DataManager.monitorContext == null)
                    DataManager.monitorContext = new tablesListEntities();
                
                context = DataManager.monitorContext;
                return context.mobjects;
            }
            public virtual List<object> getTds(){
    
                if (context == null)
                    context = new tablesListEntities();
    
                List<object> _tds = (from c in context.dbdescriptors
                                           where c.table_name == tableGridParams.mobjectName 
                                           orderby c.orderNumber
                                           select c).ToList<object>();
                return _tds;
        }

    и затем - reflection. Повторюсь, что вопрос не принципиальный, просто возникла мысль. 


    29 декабря 2015 г. 6:41
  • Очень плохое решение, но можете попробовать.

    1. Объявите эту переменную для конкретного типа:

    dbdescriptor tds = (dbdescriptor)tdsEntityOfObjectType;

    2. Поиспользуйте ее в коде везде где вам надо.

    3. Поменяйте тип на

    dynamic tds = tdsEntityOfObjectType;

    4. Все будет работать для разных типов, но это все весьма опасно т.к. вместо проверки типов на этапе компиляции получаете проверку типов на этапе выполнения...

    • Помечено в качестве ответа ATerentjev 31 декабря 2015 г. 8:31
    29 декабря 2015 г. 7:09
    Отвечающий
  • Спасибо! Похоже Вы знаете всё!

    В самом деле я придумал плохие проблемы, видимо трудности роста. Переделал по другому. 

          Для каждого объекта  someobject все делаю в someObjectRepository. Здесь все действия с объектом, выдача коллекций, примитивы с подчиненными, выдача dbDescriptors для dataGridView and mPropertytGrid. Имя конкретного Repository получаю из элемента дерева наименований таблиц. Дальше , вроде как дело техники. 

         После выбора конкретной таблицы, по имени  Repository  получаю его объект , а дальше обращаюсь к свойствам и процедурам по имени.


    • Изменено ATerentjev 30 декабря 2015 г. 12:38
    30 декабря 2015 г. 12:37
  • Окончательно я сделал так.

    В SharedModule (Prism) , который используется в любом модуле создал класс

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SharedModule.Services
    {
        public class mfield
        {
            public int id { get; set; }              // ключ в базе данных
            public string m_name { get; set; }      // имя поля
            public string m_type { get; set; }       // тип 
            public int m_length { get; set; }        // длина
            public string m_group { get; set; }      // группа
            public string m_subgroup { get; set; }   // подгруппа
            public string m_table { get; set; }      // таблица
            public string m_display { get; set; }    // видимое имя
            public int m_order { get; set; }         // номер для упорядочивания
            public bool m_visible { get; set; }      // для управления видимостью
    
            public mfield() { 
            
            }
    
    
        }
    }

    А также интерфейс

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SharedModule.Services
    {
        public interface IRepository
        {
            List<mfield> fields();
        }
    }

    В реализации интерфейса 

        public class mobjectsRepository : IRepository
        {
            List<mfield> lmfields;
    
            public mobjectsRepository(dbcuksEntities dataContext)
            {
                lmfields = fields();
            }
            public List<mfield> fields() {
    
                return (from c in cuksContext.dbfields
                            where c.m_table == "mobject"
                            select
                             new mfield
                             {
                                 m_name = c.m_name,
                                 m_type = c.m_type,
                                 m_length = c.m_length,
                                 m_group = c.m_group,
                                 m_subgroup = c.m_subgroup,
                                 m_table = c.m_table,
                                 m_display = c.m_display,
                                 m_order = c.m_order,
                                 m_visible = c.m_visible
                             }).ToList<mfield>();
            }

    • Помечено в качестве ответа ATerentjev 31 декабря 2015 г. 9:54
    31 декабря 2015 г. 8:41