Граница шрифта CSS?

Это неприятная проблема, для которой я не знаю никакого элегантного решения.

Предположим, что у вас есть эти комбинации клавиш, и вы хотите только выделить отмеченные (*).

Id1  Id2
---  ---
1    2 *
1    3
1    6
2    2 *
2    3 *
... (many more)

Как сделать так, чтобы Entity Framework была счастлива? Давайте посмотрим на некоторые возможные решения и посмотрим, хороши ли они.

Решение 1: Join (или Contains) с парами

Лучшим решением было бы создать список пар, который вы хотите, например Tuples, (List>) и соединить данные базы данных с этим списком:

from entity in db.Table // db is a DbContext
join pair in Tuples on new { entity.Id1, entity.Id2 }
                equals new { Id1 = pair.Item1, Id2 = pair.Item2 }
select entity

В LINQ для объектов это было бы прекрасно, но слишком плохо, EF генерирует исключение, подобное

Невозможно создать постоянное значение типа «System.Tuple`2 (...) В этом контексте поддерживаются только примитивные типы или типы перечисления.

blockquote>

, который является довольно неуклюжим способом сказать вам, что он не может перевести этот оператор в SQL, потому что Tuples не является списком примитивных значений (например, int или string). 1. По той же причине аналогичный оператор, использующий Contains (или любой другой оператор LINQ), потерпит неудачу.

Решение 2: In-memory

Конечно, мы могли бы превратить проблему в простой LINQ для таких объектов:

from entity in db.Table.AsEnumerable() // fetch db.Table into memory first
join pair Tuples on new { entity.Id1, entity.Id2 }
             equals new { Id1 = pair.Item1, Id2 = pair.Item2 }
select entity

Нечего и говорить, что это нехорошее решение. db.Table может содержать миллионы записей.

Решение 3: Два оператора Contains

Итак, давайте предложим EF два списка примитивных значений, [1,2] для Id1 и [2,3] для Id2. Мы не хотим использовать join (см. Примечание к стороне), поэтому давайте использовать Contains:

from entity in db.Table
where ids1.Contains(entity.Id1) && ids2.Contains(entity.Id2)
select entity

Но теперь результаты также содержат объект {1,3}! Ну, конечно, эта сущность идеально соответствует двум предикатам. Но давайте иметь в виду, что мы приближаемся.

Решение 4: Один Contains с вычисленными значениями

Решение 3 не удалось, потому что два отдельных Contains не только фильтруют комбинации своих значений. Что делать, если мы сначала создадим список комбинаций и попытаемся сопоставить эти комбинации? Из решения 1 известно, что этот список должен содержать примитивные значения. Например:

var computed = ids1.Zip(ids2, (i1,i2) => i1 * i2); // [2,6]

и оператор LINQ:

from entity in db.Table
where computed.Contains(entity.Id1 * entity.Id2)
select entity

Есть некоторые проблемы с этим подходом. Во-первых, вы увидите, что это также возвращает объект {1,6}. Комбинационная функция (a * b) не дает значений, которые однозначно идентифицируют пару в базе данных. Теперь мы могли бы создать список строк, таких как ["Id1=1,Id2=2","Id1=2,Id2=3]" и do

from entity in db.Table
where computed.Contains("Id1=" + entity.Id1 + "," + "Id2=" + entity.Id2)
select entity

(Это будет работать в EF6, а не в более ранних версиях).

Это становится довольно грязным. Но более важной проблемой является то, что это решение не является sargable , что означает: он обходит любые индексы базы данных на Id1 и Id2, которые могли быть использованы иначе. Это будет очень плохо.

Решение 5: Лучшее из 2 и 3

. Единственное жизнеспособное решение, о котором я могу думать, это комбинация Contains и join в памяти: сначала сделайте оператор contains, как в решении 3. Помните, что он приблизился к тому, что мы хотели. Затем уточните результат запроса, присоединив результат как список в памяти:

var rawSelection = from entity in db.Table
                   where ids1.Contains(entity.Id1) && ids2.Contains(entity.Id2)
                   select entity;

var refined = from entity in rawSelection.AsEnumerable()
              join pair in Tuples on new { entity.Id1, entity.Id2 }
                              equals new { Id1 = pair.Item1, Id2 = pair.Item2 }
              select entity;

Это не изящно, беспорядочно все-таки возможно, но пока это единственное масштабируемое решение этой проблемы, которое я нашел, и применяется в моем собственном коде.

Решение 6: Создайте запрос с предложениями OR

Используя построитель Predicate, такой как Linqkit или альтернативы, вы можете построить запрос, содержащий предложение OR для каждый элемент в списке комбинаций. Это может быть жизнеспособным вариантом для действительно коротких списков. С несколькими сотнями элементов запрос начнет работать очень плохо. Поэтому я не считаю это хорошим решением, если вы не можете быть на 100% уверены, что всегда будет небольшое количество элементов. Один из вариантов этой опции можно найти здесь здесь .


1 Как забавная заметка, EF делает создание инструкции SQL, когда вы присоединяетесь к примитивный список, например

from entity in db.Table // db is a DbContext
join i in MyIntegers on entity.Id1 equals i
select entity

Но сгенерированный SQL, ну, абсурд. Пример в реальной жизни, где MyIntegers содержит только 5 (!) Целых чисел, выглядит следующим образом:

SELECT 
    [Extent1].[CmpId] AS [CmpId], 
    [Extent1].[Name] AS [Name], 
    FROM  [dbo].[Company] AS [Extent1]
    INNER JOIN  (SELECT 
        [UnionAll3].[C1] AS [C1]
        FROM  (SELECT 
            [UnionAll2].[C1] AS [C1]
            FROM  (SELECT 
                [UnionAll1].[C1] AS [C1]
                FROM  (SELECT 
                    1 AS [C1]
                    FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
                UNION ALL
                    SELECT 
                    2 AS [C1]
                    FROM  ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
            UNION ALL
                SELECT 
                3 AS [C1]
                FROM  ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
        UNION ALL
            SELECT 
            4 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable4]) AS [UnionAll3]
    UNION ALL
        SELECT 
        5 AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll4] ON [Extent1].[CmpId] = [UnionAll4].[C1]

Есть n-1 UNION s. Конечно, это не масштабируемо.

Позднее дополнение: где-то по дороге к версии EF 6.1.3 это значительно улучшилось. UNION s стали проще, и они больше не вложены. Раньше запрос отказывался от менее 50 элементов в локальной последовательности (исключение SQL: Некоторая часть вашего оператора SQL слишком глубоко вложена .) Не вложенные UNION разрешают локальные последовательности до несколько тысяч (!) элементов.

2 Поскольку оператор Contains масштабируется: Масштабируемый Содержит метод LINQ для SQL-сервера

455
задан user2441511 25 October 2016 в 02:18
поделиться

4 ответа

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

<h1>with mixin</h1>
<h2>with text-shadow</h2>
<h3>with css text-stroke-width</h3>

https://codepen.io/Grienauer/pen/GRRdRJr

0
ответ дан 22 November 2019 в 22:53
поделиться

Возможно, вы могли бы эмулировать текстовый штрих, используя css text-shadow (или -webkit-text-shadow / -moz-text-shadow ) и очень низкое размытие:

#element
{
  text-shadow: 0 0 2px #000; /* horizontal-offset vertical-offset 'blur' colour */
  -moz-text-shadow: 0 0 2px #000;
  -webkit-text-shadow: 0 0 2px #000;
}

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

51
ответ дан 22 November 2019 в 22:53
поделиться

Кажется, есть свойство «text-stroke», но (по крайней мере, для меня) оно работает только в Safari.

http://webkit.org/blog/85/introduction-text-stroke/

17
ответ дан 22 November 2019 в 22:53
поделиться

Однажды я пытался сделать эти закругленные углы и отбрасывать тени с помощью css3. Позже я обнаружил, что он все еще плохо поддерживается (Internet Explorer (ы), конечно!)

В итоге я попытался сделать это в JS (холст HTML с холстом IE), но это сильно влияет на производительность (даже на моей машине C2D). Короче говоря, если вам действительно нужен эффект, подумайте о библиотеках JS (большинство из них должно работать в IE6), но не переусердствуйте из-за проблем с производительностью; если вам все еще нужна альтернатива ... вы можете использовать SFiR, затем PS и SFiR. CSS3 сегодня не готов.

0
ответ дан 22 November 2019 в 22:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: