EF Core — репозиторий, модель или модель представления

Для начала вот мои классы:

public class Name
{
    public int NameId {get;set;}
    public string Value {get;set;}
    [ForeignKey("Name_NameId")]
    public ICollection<PersonName> PersonsName {get;set;}
}

public class NameType
{
    public int NameTypeId {get;set;}
    public string Value {get;set;}
    [ForeignKey("NameType_NameTypeId")]
    public ICollection<PersonName> PersonsName {get;set;}
}

public class Person
{
    public int PersonId {get;set;}
    public string Suffix {get;set;}
    public datetime DateOfBirth {get;set;}
    [ForeignKey("Person_PersonId")]
    public ICollection<PersonName> PersonsName {get;set;}
}

public class PersonName
{
    public int Person_PersonId {get;set;}
    public int Name_NameId {get;set;}
    public int NameType_NameTypeId {get;set;}
    public int Order {get;set;}
}

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

NameId               Value
1                    John
2                    Jacob
3                    Jingleheimer
4                    Schmidt

NameTypeId           Value
1                    First Name
2                    Middle Name
3                    Last Name
4                    Nickname

PersonId             Suffix                 DateOfBirth
1                                           01/01/1900

Person_PersonId      Name_NameId            NameType_NameTypeId        Order
1                    1                      1                          0
1                    2                      2                          0
1                    3                      2                          1
1                    4                      3                          0

Итак, в классе Person я хотел бы иметь функцию/свойство, например GetFullName()/FullName, где оно будет возвращать «John Jacomb Jingleheimer Schmidt». Я работал над учебным пособием с нуля, и после создания каждого класса они затем создают интерфейс, mockrepository и работают над репозиторием db. Однако я хотел бы передать информацию в представление через модель представления, но я не уверен, как связать класс с репозиторием и т. д. Есть ли кто-нибудь, кто может указать мне учебник, который может объяснить, что лучший или по буквам это для меня? Спасибо.


person XstreamINsanity    schedule 21.06.2019    source источник
comment
Вы упомянули, что работаете над учебным пособием — можете ли вы дать нам ссылку на него?   -  person chakeda    schedule 25.06.2019
comment
@chakeda — это здесь: app.pluralsight.com/library/courses/ В этом руководстве они не делают того, что я пытаюсь сделать выше. Когда я точно следую этому руководству, все работает просто отлично. Я использовал это как начало чего-то личного, что я пытаюсь сделать.   -  person XstreamINsanity    schedule 25.06.2019
comment
Вот 40 ошибок, связанных с именами. У вашего человека должно быть только одно поле с нулевым значением для имени. Тем не менее, вы заходите слишком далеко в нормализацию базы данных. Если вы действительно хотите пойти по этому пути, ваша проблема, вероятно, заключается в отсутствующем свойстве навигации в PersonName. Затем вы можете перейти от Person через PersonName через MissingNameNavigationProperty к свойству Value.   -  person Christian Gollhardt    schedule 01.07.2019
comment
Этот дизайн базы данных ужасен, если вы не занимаетесь именами, что было бы очень распространено. Имя не должно иметь своей таблицы.   -  person Tengiz    schedule 02.07.2019


Ответы (3)


На мой взгляд, ваши таблицы слишком сложны. Недостатком является то, что вам нужно присоединиться к очень многим таблицам только для того, чтобы получить чье-то полное имя... и из-за всех объединений вы потенциально столкнетесь с проблемами производительности... этот код будет трудно понять и поддерживать другим разработчикам.

Итак, я знаю, что не отвечаю на ваш вопрос напрямую, но я бы порекомендовал вам упростить дизайн вашей таблицы.

Почему бы не использовать простую таблицу, например:

public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set;}
    public string MiddleName { get; set;}
    public string LastName { get; set; }
    public string NickName { get; set; }
    public string Suffix { get; set; }
    public datetime DateOfBirth { get; set; }

    // it is a lot easier to implement GetFullName() method here than joining so many tables
    public string GetFullName()
    {
        retun FirstName + " " + MidleName + " " + LastName;
    }
}

Я действительно изо всех сил пытаюсь понять вашу последнюю таблицу: PersonName

public class PersonName
{
    public int Person_PersonId { get; set; }
    public int Name_NameId { get; set; }
    public int NameType_NameTypeId { get; set; }
    public int Order { get; set; } // <-- Why putting Order in PersonName?
}

Для меня Order не является логическим столбцом в таблице PersonName... Я не до конца понимаю ваш дизайн и могу ошибаться... но мне кажется, что это слишком сложный дизайн.

person Hooman Bahreini    schedule 25.06.2019
comment
Одной из конечных целей этой базы данных будет предоставление пользователям возможности как можно более детального поиска людей. Столбец «Порядок» должен был использоваться для людей, у которых может быть несколько имен, отцов или фамилий. Итак, если бы чье-то имя было Боб Генри Джексон Джонс, у него было бы два средних имени. У меня было бы две записи среднего имени для этого человека, одна для Генри и одна для Джексона, с порядком 0 и 1 соответственно. Таким образом, я могу правильно упорядочить его при отображении полного имени, а также искать Генри в качестве второго имени. Это может быть слишком сложно... - person XstreamINsanity; 25.06.2019
comment
Вы хотите создать так много таблиц только для того, чтобы иметь возможность искать имена по отдельности? Я чувствую, что вы можете пожертвовать своим дизайном из-за поиска. Вы можете использовать простую таблицу, которую я предложил... тогда вы можете сделать много вещей для поиска: вы можете написать процедуру для поиска во всех столбцах имен или вы можете написать представление поверх вашей таблицы, которое будет возвращать отдельные имена... если у вас есть более сложные требования к поиску, вы можете использовать одну из многих бесплатных поисковых систем, таких как Elasticsearch ... - person Hooman Bahreini; 26.06.2019

Надеюсь я правильно понял ваши вопросы

Я сделал некоторые предположения, хотя

Я использовал ваши классы для создания базы данных и запросил базу данных, чтобы другие таблицы были связаны отношениями

Предполагая, что вы передаете идентификатор человека, а также предполагаете, что dbcontext доступен и создан внутри класса, затем вызовите GetFullName

public string GetPersonById(int personId)
{
    var person = db_context.PersonNames.FirstOrDefault(m => m.Person_PersonId == personId);
    //did not check for null here
    var name = person.Person.PersonNames.ToList();
    var fullname = "";
    name.ForEach(m => fulname += m.Name.Value + " ");
    return fullname;
}

public virtual string GetFullName
{
    get { return GetPersonById(PersonId); }// the person id passed, the class if instantiated can call this instance PersonId
    set { ; }
}

Также вы можете получить данные из базы данных в модели, которые у вас есть, и этот метод работает нормально. передача их из базы данных дает вам возможность связи, и Razor Engine может очень помочь в представлении, но

Чтобы получить данные, вам нужно будет вытащить данные один за другим и сохранить в списке.

public void UseModel()
{
    var people = _context.People.ToList();
    var names = _context.Names.ToList();
    var name_types = _context.NameTypes.ToList();

    List<PersonModel> ps = new List<PersonModel>();

    people.ForEach(m =>
    {
        ps.Add(new PersonModel
        {
            PersonId = m.PersonId,
            Suffix = m.Suffix,
            DateOfBirth = m.DateOfBirth,
            PersonsName = null//I suggest you use mapping here see https://stackoverflow.com/questions/16118085/best-practices-for-mapping-one-object-to-another
            //use mapping to map the list or use a fooloop to construct it before this declaration and assign it here
        });
    });
    //do for names and name_types

}

Вы также можете передать эти данные в View как объект PersonName, который имеет все

person Bosco    schedule 29.06.2019

Чтобы сопоставить вашу модель представления. Вы можете использовать так.

public class PersonDTO
{
    public int PersonId { get; set; }
    public string FirstName { get; set;}
    public string MiddleName { get; set;}
    public string LastName { get; set; }
    public string NickName { get; set; }
    public string Suffix { get; set; }
    public datetime DateOfBirth { get; set; }

    public string GetFullName()
    {
        retun FirstName + " " + MidleName + " " + LastName;
    }
}

Чтобы сопоставить имя, отчество, фамилию, псевдоним. Ты можешь использовать.

public void MapToPersonDTO(){

    var selectedPerson = _context.Person.FirstOrDefault(m => m.PersonId == 1);

    var personDto = new PersonDTO(){
        FirstName = _context.Name.FirstOrDefault(n=>n.NameId == selectedPerson.PersonsName.FirstOrDefault(f=>f.NameType_NameTypeId == 1)).Value,
        MiddleName= _context.Name.FirstOrDefault(n=>n.NameId == selectedPerson.PersonsName.FirstOrDefault(f=>f.NameType_NameTypeId == 2)).Value,
        LastName  = _context.Name.FirstOrDefault(n=>n.NameId == selectedPerson.PersonsName.FirstOrDefault(f=>f.NameType_NameTypeId == 3)).Value,
        NickName  = _context.Name.FirstOrDefault(n=>n.NameId == selectedPerson.PersonsName.FirstOrDefault(f=>f.NameType_NameTypeId == 4)).Value,
    };
}
person Yigit Tanriverdi    schedule 29.06.2019