Проблема с выбором результата объединения в результат - PullRequest
0 голосов
/ 09 января 2019

Я новичок в EF. Чтобы было проще, скажем, до недавнего времени у меня была такая таблица

CREATE TABLE customer
(
    CustomerNumber int,
    CustomerName nvarchar(100)
)

У меня был класс, чтобы справиться с этим

[Table("customer")]
public class Customer
{
    [Key]
    public int CustomerNumber { get; set; }
    public string CustomerName { get; set; }
}

С контекстом:

public class MyContext : DbContext
    {
        public MyContext()
                : base("name=MyContext")
        {
        }

        public DbSet<Customer> Customers { get; set; }

    }

С контроллером:

public class CustomersController : ODataController
    {
        MyContext db = new MyContext();

        private bool CustomerExists(string key)
        {
            return db.Customers.Any(p => p.CustomerNumber == key);
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        [EnableQuery(PageSize =20)]
        public IQueryable<Customer> Get()
        {
            db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
            return db.Customers;
        }

        [EnableQuery]
        public SingleResult<Customer> Get([FromODataUri] string key)
        {
            IQueryable<Customer> result = db.Customers.Where(p => p.CustomerNumber == key);
            return SingleResult.Create(result);
        }

    }

Недавно у меня появилась новая таблица с новыми данными для отображения.

CREATE TABLE customerDetails
(
    CustomerNumber int,
    Role nvarchar(20),
    ContactName nvarchar(30)
)

Для каждого номера клиента в таблице customerDetails есть 2 записи, различающиеся по роли, скажем, A и B.

Я пытаюсь получить результат следующего запроса в мою измененную сущность

Запрос:

SELECT c.CustomerNumber, c.CustomerName, cc1.ContactName as A_Name, cc2.ContactName as B_Name
FROM customer as c
JOIN customerDetails as cc1 ON c.CustomerNumber = cc1.CustomerNumber AND cc1.Role = 'A'
JOIN customerDetails as cc2 ON c.CustomerNumber = cc2.CustomerNumber AND cc2.Role = 'B'

Я изменил свою сущность:

[Table("customer")]
public class Customer
{
    [Key]
    public int CustomerNumber { get; set; }
    public string CustomerName { get; set; }
    public string A_Name { get; set; }
    public string B_Name { get; set; }
}

Добавлено:

[Table("customerDetails")]
public class Customer
{
    [Key]
    public int CustomerNumber { get; set; }
    public string Role { get; set; }
    public string ContactName { get; set; }
}

И модифицированный контроллер:

[EnableQuery(PageSize =20)]
        public IQueryable<Customer> Get()
        {
            db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
            return from c in db.Customers
                   join cc1 in db.CustomerContacts.Where(e => e.Role == "A") on c.CustomerNumber equals cc1.CustomerNumber
                   join cc2 in db.CustomerContacts.Where(e => e.Role == "B") on c.CustomerNumber equals cc2.CustomerNumber
                   select c;
        }

Но он возвращает пустой набор. Как я могу правильно написать это утверждение select и заполнить мою измененную Customer сущность?

1 Ответ

0 голосов
/ 09 января 2019

Ваши сущности должны отражать вашу общую структуру таблицы. Учитывая сущность Customer с сущностью CustomerDetails и отношение 1-многие между ними в CustomerNumber, я нацелил бы сущности на:

public class Customer
{
   public int CustomerNumber {get; set;}
   public virtual ICollection<CustomerDetails> CustomerDetails {get; set;}
}

public class CustomerDetails
{
   public int CustomerDetailId {get; set;}
   public string Role {get; set;}
   public int CustomerNumber {get; set;}
}

... и сопоставьте информацию о клиенте и клиенте. Обратите внимание, что CustomerDetails будет иметь свой собственный столбец PK, а не CustomerNumber, поскольку для одного клиента у вас потенциально может быть 2-кратная информация о клиенте (роль A и роль B)

Я бы не советовал передавать сущности в ваше представление, вместо этого создайте модель представления для представления и выберите соответствующие детали из ваших сущностей, используя .Select. Это лучше для производительности, позволяет форматировать / сглаживать данные в соответствии с вашим представлением, и намного более безопасен, чем показывать весь ваш граф сущностей для потребителя.

В качестве альтернативы, если вам нужен определенный набор связанных ролей (необязательно) для клиента, то таблица клиента должна иметь RoleACustomerDetailsId и RoleBCustomerDetailsId как int?, которые затем могут ссылаться на эти связанные объекты.

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