[英]Fluent NHibernate, HasManytoMany and Primary Key issue
我认为这应该很简单,但是使用NHibernate时,简单的事情总是最复杂的。
我有两个POCO通过HasManyToMany互相引用:
public class Foo1
{
//other properties
public virtual IList<Foo2> Foo2s {get;set;}
}
public class Foo2
{
//other properties
public virtual IList<Foo1> Foo1s {get;set;}
}
以及映射:
class Foo1Map : ClassMap<Foo1>
{
//other mappings
HasManyToMany(c => c.Foo2s);
}
class Foo2Map : ClassMap<Foo2>
{
//other mappings
HasManyToMany(c => c.Foo1s);
}
联接表是正确创建的,它具有2个字段,这些字段位于相应表的外键上,这很好,巨大的问题在于,这2个字段应该不是主键(或至少是唯一键)。 我尝试使用各种链接到HasManyToMany的流利方法,但没有任何结果。
如何获得生成的manytomany表,使其在2个外键字段上具有主键,而不必创建自定义POCO并使用复合键将其映射?
谢谢。
唯一约束和索引
class Foo1Map : ClassMap<Foo1>
{
//other mappings
HasManyToMany(c => c.Foo2s)
.ParentKeyColumns.Add("foo1_id", p => p.UniqueKey("unique_constraint1").Index("someIndex"))
.ChildKeyColumns.Add("foo2_id", p => p.UniqueKey("unique_constraint1"));
}
更新:或作为HasMany的约定(我在项目中使用的类似代码),虽然不好,但可以工作
public class IndexOneToManyColumnsConvention : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
var mappingfield = instance.Key.Columns.First().GetType()
.GetField("mapping", BindingFlags.Instance | BindingFlags.NonPublic);
var columnMapping = (ColumnMapping)mappingfield.GetValue(instance.Key.Columns.First());
if (!columnMapping.HasValue(c => c.Index))
{
var typename = instance.Member.DeclaringType.Name;
columnMapping.Index = string.Format("index_{0}_{1}",
typename.ToLower(), instance.Member.Name.ToLower());
}
}
}
我认为FNH的主干中有代码可以摆脱这种黑客攻击
我一直在遇到流利的局限性,并放弃了使用它来设置更高级的架构调整的想法。 我在设置查找表上的索引时有些头疼,因此只将SQL添加到创建后的脚本中。
我们有一个数据库项目,该项目使用NHibernate创建数据库,然后运行一个设置后创建脚本,该脚本创建索引和我们使用的存储过程。
我知道这并不能直接回答您的问题,但是昨天我在这个问题上苦苦挣扎,因此我想与您分享我的解决方案和一些代码,以便在您决定退缩的前提下让您早日入门。
看看其他人在这里做了什么很有趣!
private void ExecuteScripts(string dir, bool useTransaction = true, bool useMasterConnection = false)
{
foreach (var file in SqlFiles.Where(x => x.Contains(dir)))
{
var resource = file.Substring((Assembly.GetExecutingAssembly().GetName().Name + ".scripts.").Length);
if (useTransaction)
ExecuteSqlWithTransaction(resource, useMasterConnection);
else
ExecuteSqlWithoutTransaction(resource, useMasterConnection);
}
}
private void ExecuteSqlWithoutTransaction(string sqlFile, bool useMasterConnection = false)
{
var sql = string.Empty;
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream((Assembly.GetExecutingAssembly().GetName().Name + ".scripts.") + sqlFile.Replace('\\', '.'));
using (var reader = new StreamReader(stream))
{
sql = reader.ReadToEnd();
}
// replace the [[[dbName]]] and [[[SQLDATAFILEPATH]]] with ACTUAL DB settings we want to work with
sql = sql.Replace("[[[DBNAME]]]", DbName);
sql = sql.Replace("[[[SQLDATAFILEPATH]]]", SqlDataFilePath);
var regex = new Regex("^GO", RegexOptions.IgnoreCase | RegexOptions.Multiline);
var lines = regex.Split(sql);
var currentConnection = (useMasterConnection) ? MasterSqlConnection : SqlConnection;
using (var cmd = currentConnection.CreateCommand())
{
cmd.Connection = currentConnection;
foreach (var line in lines)
{
if (line.Length > 0)
{
cmd.CommandText = line;
cmd.CommandType = CommandType.Text;
try
{
cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
//ShowInfo("Error running script " + sqlFile + " Error: " + ex.Message);
throw new Exception(ex.Message);
}
}
}
}
}
ALTER TABLE [dbo].[ArticleProjectAssignments] ADD CONSTRAINT [pk_ArticleProjectAssignments] PRIMARY KEY CLUSTERED
(
[ArticleId] ASC,
[ProjectId] ASC
)
GO
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.