これは私には SQL の質問のように見えるので、それに応じて答えます。SQL ベースの回答を探していない場合は、質問をより明確にしてください。もしそうなら、あなたのタグを修正してください。
型の数が固定され、既知である限り、次の SQL は基になる SQL クエリを形成できます (ソースが SQL データベースであると仮定します)。
SELECT a.StaffID, Name,
CASE WHEN b.ID IS NOT NULL THEN 1 ELSE 0 END AS Type1,
CASE WHEN c.ID IS NOT NULL THEN 1 ELSE 0 END AS Type2,
CASE WHEN d.ID IS NOT NULL THEN 1 ELSE 0 END AS Type3
FROM dbo.Staff a
LEFT JOIN dbo.StaffType b ON a.StaffID = b.StaffID AND b.TypeID = 1
LEFT JOIN dbo.StaffType c ON a.StaffID = c.StaffID AND c.TypeID = 2
LEFT JOIN dbo.StaffType d ON a.StaffID = d.StaffID AND d.TypeID = 3
GridView では、各チェックボックスはその StaffID (行から) と TypeID (列から) を認識するため、その OnChanged イベントを処理し、次のように呼び出します。
DECLARE @StaffID INT = 1, @TypeID INT = 1
IF EXISTS (SELECT * FROM dbo.StaffType WHERE StaffID = @StaffID AND TypeID = @TypeID)
DELETE FROM dbo.StaffType WHERE StaffID = @StaffID AND TypeID = @TypeID
ELSE
INSERT INTO dbo.StaffType ( StaffID, TypeID )
VALUES ( @StaffID, @TypeID )
LINQ バージョンで更新:
var q2 =
from staff in staffList
from type1 in typesList
.Where(t => t.StaffID == staff.StaffID && t.TypeID == 1)
.DefaultIfEmpty()
from type2 in typesList
.Where(t => t.StaffID == staff.StaffID && t.TypeID == 2)
.DefaultIfEmpty()
from type3 in typesList
.Where(t => t.StaffID == staff.StaffID && t.TypeID == 3)
.DefaultIfEmpty()
select new
{
StaffID = staff.StaffID,
Name = staff.Name,
Type1 = (type1 != null),
Type2 = (type2 != null),
Type3 = (type3 != null)
};