<\s*(\w+)[^/>]*>
Объясненные детали:
<
: начальный символ
\s*
: он может иметь пробелы перед именем тега (уродливым, но возможным).
(\w+)
: теги могут содержать буквы и цифры (h1). Ну,\w
также соответствует «_», но это не мешает, я думаю. Если любопытное использование ([a-zA-Z0-9] +).
[^/>]*
: все, кроме>
и/
, до закрытия>
>
: закрытие>
UNRELATED
И для парней, которые недооценивают регулярные выражения, говоря, что они только настолько сильны, как обычные языки:
anbanban, который не является регулярный и даже контекстно-свободный, можно сопоставить с
^(a+)b\1b\1$
Обратное обращение FTW !
Ответ на вопрос, почему это происходит, это (после некоторых исследований) довольно интересный и хороший пример того, почему знание того, как работает EF Core, важно для его использования.
Линк вообще работает над идеей отложенного исполнения. Проще говоря, если я сделаю оператор Linq для конкретной строки, он может не быть оценен или выполнен до тех пор, пока данные «не понадобятся». Большую часть времени мы сокращаем это с помощью .ToList (), который вызывает немедленное выполнение. Общая идея здесь заключается в том, что иногда наборы данных не нужны (скажем, если исключение происходит до того, как оно будет оценено, но после того, как оно будет «загружено»).
EF Core делает еще один шаг вперед и связывает идею отложенного выполнения с оптимизацией базы данных. Если, например, я получаю подмножество данных из базы данных:
var result = _context.SomeTable.Where(x => x.name == "SomeValue");
Но позже все, что меня волнует, это размер набора данных:
return result.Count;
Вызов DB может оптимизировать до
select count(*) from SomeTable where name = "SomeValue";
вместо
select * from SomeTable where name = "SomeValue";
Аналогично, мой запрос, который я описал выше, был оптимизирован. Поскольку я все это приковал цепью до того, как она была оценена, оптимизатор EF Core выбросил мне нужную таблицу.
Причина, по которой это работает:
var user = new Guid(id);
var userCustAffs = _data.UserCustomerAffiliation.Include(x => x.Customer)
.ThenInclude(x => x.Brand).Where(x =>
x.UserId.Equals(user)).ToList();
var result = userCustAffs.Select(p => p.Customer).ToList();
Это потому, что я принудительно выполняю запрос, похожий на
Select u.*, c.*, b.* from usercustomeraffiliation u,
inner join Customer c on u.customerid = c.id
inner join Brand b on c.brandid = c.id
where u.userid = 'userId';
, а затем вычеркиваю объект клиента (и объект бренда под ним) в памяти. Было бы эффективнее иметь возможность генерировать запрос вроде:
Select c.*, b.* from Customer c on u.customerid = c.id
inner join Brand b on c.brandid = c.id
where c.id in (select u.customerid from usercustomeraffiliation u
where u.userid = 'userId');
Но это оптимизируется.