Вы правы - без проверки подлинности сертификата на клиенте и сервере есть открытие для человека в средней атаке.
SSL может быть «безопасным в обоих направлениях», если вы используете взаимная аутентификация также называется двухсторонним SSL .
Причина, по которой первый сценарий не работает, заключается в том, что System.Linq.IQueryable
является интерфейсом, который реализуется, среди прочих, классом System.Data.Entity.DbSet
. В C #, если класс C
реализует интерфейс I
, когда дело доходит до переходов между типами, вы можете также рассматривать I
как базовый класс C
(даже семантика class C : I
предлагает такой подход) , И поскольку вы не можете неявно (то есть не дословно) использовать класс (или интерфейс) для одного из его классов-потомков, вы получаете ошибку времени компиляции при попытке сделать это. Вы можете сделать обратное, то есть неявно применить класс потомков к его базовому классу (или интерфейсу). Это то, что происходит во втором сценарии.
В вашем случае вы можете обмануть компилятор, произнеся явно:
query = (DbSet<Customer>) query.Where(p => p.Id == id);
, но я бы настоятельно советовал вам не с тех пор, ll заканчивается беспорядочным исключением, потому что результат query.Where(p => p.Id == id)
на самом деле не является экземпляром DbSet<Customer>
, а скорее некоторым классом, представляющим результат запроса, выполненного на DbSet<Customer>
, который реализует интерфейс IQueryable
.
Итак, чтобы подвести итог, давайте рассмотрим все сценарии:
Сценарий 1:
//query is of type DbSet<Customer>
var query = _db.Products;
if (bool) {
//here you're trying to assign a value of type IQueryable<Customer>
//to a variable of it's descendant type DbSet<Customer>
//hence the compile-time error
query = query.Where(p => p.Id == id);
}
Сценарий 2:
//here you implicitly cast value of type DbSet<Customer>
//to IQueryable<Customer>, which is OK
IQueryable<Customer> query = _db.Products;
if (bool) {
//here you're assigning a value of type IQueryable<Customer>
//to a variable of the same type, which is also OK
query = query.Where(p => p.Id == id);
}
Сценарий 3:
//I assume you have the following line in your code
var products = _db.Products;
//query is of type IQueryable<Customer>, because you perform
//a query on the DbSet<Product>
var query = from product in products
select product;
if (bool) {
//here you're assigning a value of type IQueryable<Customer>
//to a variable of the same type, which is OK
query = query.Where(p => p.Id == id);
}
Это потому, что _db.Products
не является запросом, это DbSet.
Второй блок работает, потому что вы его передаете в IQueryable, а последний работает, потому что это фактический запрос.
DbSet
и присваиваю ему общий. DbSet
получает бросок?
– Boy Pasmo
23 February 2014 в 16:42
DbSet
, особенно в этом контексте. Просто запросите базу данных.
– dursk
23 February 2014 в 16:52
При использовании var
компилятор выводит тип выражения справа от присваивания. Когда вы пишете
var query = _db.Products;
query
имеет тип DbSet<Product>
, и ему не может быть назначено какое-либо IQueryable<Product>
, которое возвращает метод расширения Where
.
Когда вы использовали синтаксис запроса, query
снова IQueryable<Product>
, что заставило его работать. Это эквивалентно записи
var query = products.Select(t => t);
. Метод расширения Select
, например Where
, возвращает IQueryable<Product>
.
var query = _db.Products.Where(x => true);
if (bool) {
query = query.Where(p => p.Id == id);
}