Come mappare NHibernate dalla tabella A alla tabella A stessa con molti-a-molti?
-
03-07-2019 - |
Domanda
Per favore aiutatemi! Non sono riuscito a capire come mappare la seguente situazione:
Ho solo 1 tabella.
[Tabella] Utente {id, nome}
La mia classe si presenta così
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public ISet<User> Friends { get; set; }
}
Ogni utente ha una relazione con altri utenti. ad es. "L'utente A" può avere molti amici che sono altri utenti.
Quale dovrebbe essere la mappatura per questo? Penso che questo dovrebbe essere un rapporto molti-a-molti, ma non so davvero come sarà l'HBM?
Grazie,
Soluzione
Penso che questo dovrebbe essere Many-to-Many rapporto
Hai ragione. Nel tuo scenario dovrai usare una mappatura molti-a-autoreferenziale. Ma usando una singola tabella Utenti non puoi rappresentare la relazione tra utenti e amici (usando una singola tabella potresti rappresentare un autoreferenziale parent-child ). Per raggiungere questo obiettivo avrai bisogno di una tabella intermedia. Ecco un esempio usando SQLite ADO.NET provider per mostrare un possibile modo di modellare il tuo scenario:
User.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Test" assembly="test">
<class name="User" table="Users">
<id name="Id" column="id">
<generator class="native"/>
</id>
<property name="Name" column="name"/>
<set name="Friends" table="Friends">
<key column="user_id"/>
<many-to-many class="User" column="friend_id"/>
</set>
</class>
</hibernate-mapping>
Dalla mappatura sopra noterete l'uso delle seguenti tabelle: Utenti e amici
Ed ecco il codice:
using System;
using System.IO;
using System.Collections.Generic;
using System.Data.SQLite;
using NHibernate;
using NHibernate.Cfg;
using Iesi.Collections.Generic;
namespace Test
{
class Program
{
public static void Main()
{
if (File.Exists("nhibernate.db"))
{
File.Delete("nhibernate.db");
}
ExecuteCommand("create table Users (id integer, name string)");
ExecuteCommand("create table Friends (user_id integer, friend_id string)");
ExecuteCommand("insert into Users (id, name) values (1, 'user1')");
ExecuteCommand("insert into Users (id, name) values (2, 'user2')");
ExecuteCommand("insert into Users (id, name) values (3, 'user3')");
// User1 is friend with User2
ExecuteCommand("insert into Friends (user_id, friend_id) values (1, 2)");
// User1 is friend with User3
ExecuteCommand("insert into Friends (user_id, friend_id) values (1, 3)");
// User2 is friend with User1
ExecuteCommand("insert into Friends (user_id, friend_id) values (2, 1)");
// User3 is friend with User1
ExecuteCommand("insert into Friends (user_id, friend_id) values (3, 1)");
ISessionFactory sessionFactory =
new Configuration().Configure().BuildSessionFactory();
ISession session = sessionFactory.OpenSession();
User user = session.Get<User>(1);
Console.WriteLine(user.Friends.Count);
session.Close();
sessionFactory.Close();
}
private static void ExecuteCommand(string sql)
{
using (SQLiteConnection connection = new SQLiteConnection("Data Source=nhibernate.db;Version=3"))
using (SQLiteCommand command = new SQLiteCommand(sql, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
}
class User
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<User> Friends { get; set; }
}
}
E infine per completezza ecco il mio file di configurazione:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"
/>
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
<property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
<property name="connection.connection_string">Data Source=nhibernate.db;Version=3</property>
<mapping assembly="test" />
</session-factory>
</hibernate-configuration>
</configuration>