Я работаю с EntityFramework, но можно использовать и другие способы, при необходимостизапроса Структура дерева
Вот так: у меня есть базы данных SQL Server с той же схемой:
A B C AhasB AhasC
________ ________ ________ __________ ___________
AId BId CId AId AId
... Btxt Ctxt BId CId
BParent ...
...
Where ...
средств другие столбцы не важны для проблемы.
Таблицы C
и AhasC
там хранить данные в течение длительного процесса и очищаются по окончании процесса, поэтому я всегда начинаю с пустыми Теперь процесс получения много данных (1000+ записей) из интернет-источников и хранит его в C
. После C
заполнена, я хочу, чтобы заполнить таблицу AhasC
на основе следующего:
INSERT INTO C (AId, CId) VALUES (
SELECT A.AId, C.CId
FROM A, B, C, AhasB
WHERE A.AId = AhasB.AId AND B.BId = AhasB.BId AND
C.CTxt IN (
SELECT D.BTxt
FROM B AS D
WHERE D.BId = B.BId OR ??
)
)
Прежде чем я объясню, что мне нужно в ??
позвольте мне бежать через то, что я есть здесь:
Я хочу, чтобы вставить в таблицу AhasC - пара A.AId, C.CId, так что во всех парах C.CTxt
совпадает с B.Btxt
, который соединен с A в AhasB
.
Более того (и здесь входит ??
) Я также хочу, чтобы он соответствовал B.Btxt
любого родителя B
.
Пример:
A B
_______ ____________________________________
AId = 1 BId = 1, BTxt = 'a', BParent = Null
AId = 2 BId = 2, BTxt = 'b', BParent = 1
AId = 3 Bid = 3, BTxt = 'c', BParent = 2
AId = 4 BId = 4, BTxt = 'x', BParent = Null
C AahsB
_____________________ _________
CId = 1, Ctxt = 'b' AId = 1, BId = 3
CId = 2, CTxt = 'z' AId = 3, BId = 4
Это должно привести к:
AhasC
____________
AId = 1, CId = 1
Так опять же, AhasC
необходимо подключить A
и C, если A
подключен к B
, что либо имеет BTxt
равным CTxt
, или у которого есть родитель (или grand-parent и т. д.), есть BTxt, то же самое, что и CTxt
.
Надежда я не усложнять мой объяснения здесь: р
EDIT1: согласно коментарии @ dotctor, вот это образ моей реальной Шма (не то, что я думаю, что это добавит много к вопросу)
A = Contatos
B = Termos
C = ConcursosPublicos
AhasB = TermosContatos
AhasC = ConcursosContatos
A.AId = Contatos.Id
B.BId = Termos.Id
C.CId = ConcursosPublicos.Id
B.BTxt = Termos.Area
C.CTxt = ConcursosPublicos.Area
B.BParent = Termos.Pai
А вот мой реальный код делает эту работу в настоящее время:
public static void Connect(ProgressBar progress)
{
lock (Locker)
using (var ctx = new ConcursosContainer())
{
int i = 0;
IList<Contatos> contatos = ctx.Contatos.ToList();
progress.Invoke((MethodInvoker) (() =>
{
progress.Value = 0;
progress.Maximum = contatos.Count;
}));
foreach (Contatos contato in contatos)
{
Console.WriteLine(contato.Id);
List<Termos> tree = GetTree(ctx, contato.Id).SelectMany(x => x.ToArray()).ToList();
List<int> attr = ctx.ConcursosContatos.Where(x => x.ContatoId == contato.Id).Select(x => x.ConcursoId).ToList();
IList<ConcursosPublicos> concursosPublicos = ctx.ConcursosPublicos.Where(x => !attr.Contains(x.Id)).ToList();
foreach (ConcursosPublicos concursosPublico in concursosPublicos)
{
if (tree.Any(termo => (termo.Tipo == concursosPublico.TipoConc) && concursosPublico.Area.Trim().EndsWith(termo.Area)))
{
ctx.ConcursosContatos.Add(new ConcursosContatos
{
ContatoId = contato.Id,
ConcursoId = concursosPublico.Id
});
i++;
}
if (i == 9)
{
ctx.SaveChanges();
i = 0;
}
}
progress.Invoke((MethodInvoker) (progress.PerformStep));
}
if (i > 0)
ctx.SaveChanges();
}
}
private static IEnumerable<Stack<Termos>> GetTree(ConcursosContainer ctx, int id)
{
var res = new List<Stack<Termos>>();
IQueryable<Termos> terms = ctx.Termos.Where(x => ctx.TermosContatos.Any(y => (y.ContatoId == id) && (y.TermoId == x.Id)));
foreach (Termos term in terms)
{
var stack = new Stack<Termos>();
if (term.Pai.HasValue)
AddParent(ctx, stack, term);
stack.Push(term);
res.Add(stack);
}
return res;
}
private static void AddParent(ConcursosContainer ctx, Stack<Termos> stack, Termos term)
{
Termos pai = ctx.Termos.First(x => x.Id == term.Pai.Value);
if (pai.Pai.HasValue)
AddParent(ctx, stack, pai);
stack.Push(pai);
}
Этот код выполняет работу, но для более 1000 членов ConcursosPublicos и 7000+ участников Contatos (с контатами на пути к росту в будущем) для завершения может потребоваться от 15 до 20 часов. Так как это ежедневный процесс, мне нужен более эффективный способ заполнить ConcursosContatos
'AhasB' и' AhasC' генерируются инфраструктурой сущностей? Можете ли вы опубликовать код для своих POCOs? – dotctor
Они были созданы с использованием EntityFramework Model-First - поэтому poco автоматически генерируется - есть ли что-то конкретное, что вы хотите увидеть? – 537mfb
Итак, у вас есть объекты с именем 'AhasB' и' AhasC'? – dotctor