我正在使用EntityFramework,但如果需要可以使用其他方式
情况就是这样:我有一个SQL Server数据库,其方案类似于:
A B C AhasB AhasC
________ ________ ________ __________ ___________
AId BId CId AId AId
... Btxt Ctxt BId CId
BParent ...
...
其中...
表示对问题不重要的其他列。
表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
中与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
必须连接A
和C B
与BTxt
相关CTxt
等于CTxt
或者谁的父母(或祖父母等)的BTxt与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
相同。
希望我的解释不会过于复杂化:p
EDIT1:根据@ dotctor的评论,这是我真正的谢玛的形象(不是我认为它会增加很多问题)
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);
}
这是我现在正在做这项工作的真实代码:
RelativeLayout
此代码可以完成这项工作,但是对于ConcursosPublicos的1000多名成员和Contatos的7000多名成员(未来将继续增长的contatos),可能需要15到20个小时才能完成。由于这是一个日常过程,我需要一种更有效的方式来填写ConcursosContatos
答案 0 :(得分:0)
您需要一些递归来获取B表上的族谱。在SQL Server中,您可以使用CTE执行此操作:
;with chld as (
select B.BId, B.BTxt, B.BParent
from dbo.B as B
union all
select chld.BId , b1.BTxt, b1.BParent
from dbo.B as B1
inner join chld
on B1.BId = chld.BParent
)
select BId, BTxt from chld option(maxrecursion 32767)
结果集:
BId BTxt
1 a
2 b
3 c
4 x
3 b
3 a
2 a
如果这不正确,则无需再继续。否则,您可以根据需要将其连接到其他表以填充AhasC表。