NHibernate多对多标准任务标记示例
我在任务和标记之间建立了简单的多对多关系。一个任务可能有许多标记,一个标记可能被分配给许多任务。我使用三个表来管理此任务—Task、Tag和TaskTag。到目前为止还不错 我正在尝试为下面的示例编写一个条件查询NHibernate多对多标准任务标记示例,hibernate,nhibernate,many-to-many,Hibernate,Nhibernate,Many To Many,我在任务和标记之间建立了简单的多对多关系。一个任务可能有许多标记,一个标记可能被分配给许多任务。我使用三个表来管理此任务—Task、Tag和TaskTag。到目前为止还不错 我正在尝试为下面的示例编写一个条件查询 Find all tasks that are tagged with 'Apple' (id = 1718) AND 'Orange' (id = 1717) 我发现下面的例子,我试图遵循 这是它生成的SQL SELECT this_.ID as ID4_0_, [MORE COL
Find all tasks that are tagged with 'Apple' (id = 1718) AND 'Orange' (id = 1717)
我发现下面的例子,我试图遵循
这是它生成的SQL
SELECT this_.ID as ID4_0_, [MORE COLS HERE]
FROM dbo.[Task] this_
WHERE exists (
SELECT this_0_.ID as y0_
FROM dbo.[Task] this_0_
inner join dbo.TaskTag tags3_ on this_0_.ID=tags3_.TaskID
inner join dbo.[Tag] tag1_ on tags3_.TagID=tag1_.ID
WHERE this_0_.ID = this_0_.ID
and tag1_.ID in (2, 1718) <------ 1
GROUP BY this_0_.ID
HAVING count(this_0_.ID) = 1717 <------ 2
)
由于某些原因,我无法清楚地理解,参数被放错了位置
请注意,它将计数2错误地放在in列表中,并且
然后,它将第二个标记id放在计数应该去的地方。
当我修改SQL以将参数放在正确的位置时,它就工作了
我的标准一定不正确,但我看不出来
谢谢你的帮助。谢谢 这是我的解决方案
实体:
public class TaskTest : Entity<TaskTest>
{
public virtual string Name { get; set; }
public virtual IList<TagTest> Tags { get; set; }
public TaskTest()
{
Tags = new List<TagTest>();
}
}
public class TagTest : Entity<TagTest>
{
public virtual string Name { get; set; }
}
问候,,
/爱雍谢谢!我就是看不出问题所在。使用CreateAlias对我来说比CreateCriteria更清楚。
public class TaskTest : Entity<TaskTest>
{
public virtual string Name { get; set; }
public virtual IList<TagTest> Tags { get; set; }
public TaskTest()
{
Tags = new List<TagTest>();
}
}
public class TagTest : Entity<TagTest>
{
public virtual string Name { get; set; }
}
public class TaskTestMap : EntityMap<TaskTest>
{
public TaskTestMap()
{
Map(x => x.Name).Not.Nullable().Length(512);
HasManyToMany(x => x.Tags).Table("TaskTag").Cascade.All();
}
}
public class TagTastMap : EntityMap<TagTest>
{
public TagTastMap()
{
Map(x => x.Name).Not.Nullable();
}
}
public IList<TaskTest> GetTaskByTagIds(IList<long> tagIds)
{
DetachedCriteria exists = DetachedCriteria.For<TaskTest>("t")
.CreateAlias("t.Tags", "tags")
.Add(Restrictions.EqProperty("t.Id", "task.Id"))
.Add(Restrictions.In("tags.Id", tagIds.ToArray()))
.SetProjection(Projections.GroupProperty("t.Id"))
.Add(Restrictions.Eq(Projections.Count("t.Id"), tagIds.Count));
ICriteria criteria = GetSession().CreateCriteria<TaskTest>("task")
.Add(Subqueries.Exists(exists));
return criteria.List<TaskTest>();
}
[Test]
public void TestTaskTest()
{
//Insert data;
var task1 = new TaskTest {Name = "task1"};
var task2 = new TaskTest {Name = "task2"};
var task3 = new TaskTest {Name = "task3"};
var tag1 = new TagTest {Name = "tag1"};
var tag2 = new TagTest {Name = "tag1"};
var tag3 = new TagTest {Name = "tag1"};
task1.Tags.Add(tag1);
task1.Tags.Add(tag2);
task2.Tags.Add(tag1);
task2.Tags.Add(tag3);
task3.Tags.Add(tag3);
_repository.AddToSession(task1);
_repository.AddToSession(task2);
_repository.AddToSession(task3);
FlushAndClearSession();
//We will try to get all task which a taged with tag1 and tag2. The result should be task1
var tagsId = new List<long> {tag1.Id, tag2.Id};
var result = _repository.GetTaskByTagIds(tagsId);
Assert.That(result, Is.Not.Null);
Assert.That(result, Is.Not.Empty);
Assert.That(result.Count, Is.EqualTo(1));
Assert.That(result[0].Name, Is.EqualTo("task1"));
}
exec sp_executesql N'SELECT this_.Id as Id50_0_, this_.Version as Version50_0_, this_.Name as Name50_0_
FROM [TaskTests] this_
WHERE exists (
SELECT this_0_.Id as y0_
FROM [TaskTests] this_0_
inner join TaskTag tags3_ on this_0_.Id=tags3_.TaskTestId
inner join [TagTests] tags1_ on tags3_.TagTestId=tags1_.Id
WHERE this_0_.Id = this_.Id and tags1_.Id in (@p0, @p1)
GROUP BY this_0_.Id
HAVING count(this_0_.Id) = @p2)',
N'@p0 bigint,@p1 bigint,@p2 int',
@p0=9000,@p1=9001,@p2=2