写完这个问题后,创造了一个MCVE,听起来有点像家庭作业,但实际上它不是...... 不幸的是,我太老了,无法完成作业。
我正在尝试编写一个小应用程序来填充我正在使用'金字塔'结构的数据库。 有一个原始成员,他指的是10个成员。 这些推荐中的每一个都可以有10个推荐。其中每个都有10个转介。等等...
我正在尝试使用最大数量的成员(已提供)填充数据库
如果我将最大成员数设置为100,000 - 这是有效的。 但是,200,000会引发StackOverflow异常。
我很确定这不是因为我没有尽早终止'扇出'。但我无法为我的生活弄清楚在哪里。
注意,下面我的MCVE使用Dapper是为了简单起见,因此简单的INSERT INTO
语句
public class MemberPopulator
{
private readonly SqlConnection connection;
private const string MemberSql = @"
INSERT INTO Members (FirstName, LastName, ReferralId, Active, Created)
VALUES (@FirstName, @LastName, @ReferralId, @Active, @Created);
SELECT CAST(SCOPE_IDENTITY() as int)";
private int TotalMemberCount;
private const int MaxMemberCount = 200000;
public MemberPopulator()
{
connection = new SqlConnection("Data Source=localhost;Initial Catalog=MyTestDb;Integrated Security=True");
}
public void CreateMembers()
{
//clear members
connection.Execute("TRUNCATE TABLE Members");
//create the 'original' member (top of pyramid)
var originalMemberId = connection.Query<int>(MemberSql, new Member
{
FirstName = "FirstName Goes Here",
ReferralId = 0
}).Single();
//now we have 1 total members
TotalMemberCount = 1;
//recursively create members, starting with original member,
RecursiveCreate(new[] { originalMemberId });
}
private void RecursiveCreate(IEnumerable<int> referralMemberIds)
{
//don't recurse if we've already got enough members
if (TotalMemberCount >= MaxMemberCount)
return;
foreach (var referralId in referralMemberIds)
{
//Create 10 members
var refs = CreateReferredMembers(referralId, 10);
RecursiveCreate(refs);
}
}
private IEnumerable<int> CreateReferredMembers(int referralId, int numberOfReferrals)
{
var referredMemberIds = new List<int>();
for (var i = 0; i < numberOfReferrals; i++)
{
if (TotalMemberCount >= MaxMemberCount)
break;
var member = new Member
{
FirstName = "FirstName Goes Here",
ReferralId = referralId
};
var memberId = connection.Query<int>(MemberSql, member).Single();
referredMemberIds.Add(memberId);
TotalMemberCount++;
}
return referredMemberIds;
}
}
答案 0 :(得分:1)
C#中的堆栈对于32位应用程序设置为1MB,对于64位应用程序设置为4MB by default。这适用于大多数应用。如果您需要更多信息,请遵循网络中的指导(例如this one)。
如果您不确切知道递归级别,我建议使用Stack或Queue数据类型来模拟递归。
public class MemberPopulator
{
private readonly SqlConnection connection;
private const string MemberSql = @"
INSERT INTO Members (FirstName, LastName, ReferralId, Active, Created)
VALUES (@FirstName, @LastName, @ReferralId, @Active, @Created);
SELECT CAST(SCOPE_IDENTITY() as int)";
private int TotalMemberCount;
private const int MaxMemberCount = 200000;
public MemberPopulator()
{
connection = new SqlConnection("Data Source=localhost;Initial Catalog=MyTestDb;Integrated Security=True");
}
public void CreateMembers()
{
//clear members
connection.Execute("TRUNCATE TABLE Members");
//create the 'original' member (top of pyramid)
var originalMemberId = connection.Query<int>(MemberSql, new Member
{
FirstName = "FirstName Goes Here",
ReferralId = 0
}).Single();
//now we have 1 total members
TotalMemberCount = 1;
//recursively create members, starting with original member,
NonRecursiveCreate(originalMemberId);
}
private void NonRecursiveCreate(int root)
{
Queue<int> members = new Queue<int>();
members.Enqueue(root);
while (members.Any() && TotalMemberCount < MaxMemberCount)
{
var referralId = members.Dequeue();
//Create 10 members
var refs = CreateReferredMembers(referralId, 10);
foreach (int i in refs)
{
members.Enqueue(i);
}
}
}
private IEnumerable<int> CreateReferredMembers(int referralId, int numberOfReferrals)
{
var referredMemberIds = new List<int>();
for (var i = 0; i < numberOfReferrals; i++)
{
if (TotalMemberCount >= MaxMemberCount)
break;
var member = new Member
{
FirstName = "FirstName Goes Here",
ReferralId = referralId
};
var memberId = connection.Query<int>(MemberSql, member).Single();
referredMemberIds.Add(memberId);
TotalMemberCount++;
}
return referredMemberIds;
}
}