I have a simple entity that has an Id (the primary key) and a string name. I'm looking for a way to tell nHibernate not to allow duplicate names in the table.
I'd like to have an Add method that can take a new entity (with Id = 0), and if necessary add the new entity & update Id. This works now. If the name already exists in the table, I want to simply update Id and return the existing Id.
I'd like to be able call it like this:
Foo foo = new Foo(name); // foo.Id = 0
FooRepository.Add(foo);
.. and afterwards foo.Id <> 0 and it was either added or an existing foo.name was found and its Id was returned.
thanks/jf
You have to set the unique attribute equal to true in the mapping file in order to make this a unique column.
<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>
If you intend for the column to be a primary key for that table, then put
<id name="CommentId">
<column name="comment_id" not-null="false"/>
<generator class="identity"/>
</id>
The column will automatically have a unique constraint on it.
I dont think nhibernate can match additionally on natural key . You would have to do that in the add method in the repository .
i.e Look up by name ,if found update the name and save.( find by example might save you sometime here )
Looks like you want to use assigned id's instead of surrogate id here .
May be map name as identifier and get rid of surrogate key
Related
I am trying to insert values into a database. I think the SQL would look like this:
INSERT INTO `tb_config` (`name`, `value`, `description`, `unity_id`)
(SELECT 'new_rule', true, 'rule description', id FROM tb_unity );
However, I want to do it with Liquibase, using a changeset:
<changeSet author="Luis Sukys" id="1022" >
<insert tableName="tb_config">
<column name="name">new_rule</column>
<column name="value">false</column>
<column name="descricao">rule description</column>
<column name="unidade_id" valueComputed="SELECT id FROM tb_unity" />
</insert>
</changeSet>
I've seen the use of valueComputed but with a where clause.
The idea is that it includes one row in tb_config for each id in tb_unity.
I am actually getting a 'ValidationFailedException' from liquibase.
Any help?
I use Navicat with MySQL and when I run this code, it includes one new row int tb_config for each row in tb_unity. The field i use from tb_unity is 'id'.
If I have 05 unities in tb_unity, it must add 05 rows in tb_config, with same values, only change the unity's id.
If you try running that SQL using whatever SQL tool you use, you will see that the problem is that you do indeed need a where clause. Which row of tb_unity do you want to use the id from?
How can i create a table, that allows only to put data in NAME, if the data matches with the data that i want to be allowed in NAME. So like Bla1 or Bla2.
CREATE TABLE Table1 (
NAME VARCHAR(23)
NAME has to be one of them: ('Bla1', 'Bla2')
)
The best way to do it is probably to have a second table with all the allowed names in it, and making a FOREIGN KEY from the name field in your Table1 to the name field in that other table. That'll automatically fail any insert queries for which the name is not contained in the list of allowed names.
This has an advantage over things like ENUM and such in that it does not require you to rebuild your table (which is a very expensive operation) every time you want to allow another name and it also allows you to later add additional related info to each name by adding it to the other table.
Here's a great article on why using a foreign key is much better than using enums or other such checks in the table itself: http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/
Try this:
CREATE TABLE Table1 (
name VARCHAR(23) CHECK( name IN ('Bla1','Bla2') )
);
Someone deployed a SQL table with the schema
ConfigOptions
name VARCHAR(50)
value VARCHAR(50)
and the following logic for saving options:
int i = ExecuteNonQuery("UPDATE ConfigOptions SET value=#value WHERE name=#name");
if(i==0) i = ExecuteNonQuery("INSERT INTO ConfigOptions (name,value) (#name,#value)");
We now saw that this table is littered with duplicates, and we want to change this.
As far as I can tell, the logic is: whenever the UPDATE affected zero rows, another row is inserted. If I am not mistaken, this can be caused by:
a row by the name of #name does not exist or
the row exists, but already contains value #value
So, all rows with same name should be full duplicates. If now, something is completely wrong (and behaviour may be undefined).
Now I have to fix this problem of duplicates, so I want to add a PK on name. Before I can do this, I have to remove all rows with duplicate names, only keeping one of each.
In the installer (only the installer is allowed to change schema), I only have SQL queries at hand, so I can't do it with C# logic:
Dictionary<string, int> dic = new Dictionary<string, int>();
SqlDataReader sdr = ExecuteReader("SELECT name,COUNT(value) FROM ConfigOptions GROUP BY name HAVING COUNT(value)>1");
while (sdr.Read()) dic.Add(sdr.GetString(0), sdr.GetInt32(1));
sdr.Close();
foreach (var kv in dic) {
AddParameter("#name", System.Data.SqlDbType.VarChar, 50, kv.Key);
ExecuteNonQuery("DELETE TOP " + (kv.Value - 1) + " FROM ConfigOptions WHERE name=#name");
}
ExecuteNonQuery("ALTER TABLE program_options ADD PRIMARY KEY (name)");
Is there a way to put this into SQL logic?
Using %%physloc%%, the phys(ical) loc(ation) of the row, should do the trick:
DELETE FROM ConfigOptions
WHERE %%physloc%% NOT IN (
SELECT MIN(%%physloc%%)
FROM ConfigOptions
GROUP BY name);
After this cleanup, you can add the primary key to the table.
NOTE: this will leave you with only one row for every name. If the value column is different in two records with the same name, you will lose the newest record. If you want to change this, use GROUP BY name, value.
Have been looking this up in Google but could not find anything.
Wanted to know if there is a way in SQL Server 2005 that I could use Name Value pairs to update records in the db.
I have a list of Name Value pairs and want to update all the records where Name could be found as a columm value (something that you would specify in where clause) and if the record is found ... update the record with the Value paired with the name
For instance, something like
update X set column_value = <Value paired with the Name> where column_name = <Name from the list>
P.S. I have a list of more than 1000 records and this could be more.
The obvious way is to store your pair values in separate table. E.g. :
map(name,value)
And update your table using join. E.g :
update m1 set m1.column_value = m2.value
from mytable m1 join map m2 on m1.column_name = m2.name
I have the Tables
PatientEligibilit
and
PatientsEligibilitiesDoctorsSpecialties
and
DoctorsSpecialties
PatientEligibilit
has foreign key PatientsEligibilitiesDoctorsSpecialtyID from
PatientsEligibilitiesDoctorsSpecialties
table
and
PatientsEligibilitiesDoctorsSpecialty
has foreign key DoctorsSpecialtyID from
DoctorsSpecialties
table
THEN USING VB.NET LINQ: i'm tring to add child item ( PatientsEligibilitiesDoctorsSpecialty)
to it's parent (PatientEligibilit)
then I submit Changes
like :
PatientEligibilityObject.PatientsEligibilitiesDoctorsSpecialties.Add(New PatientsEligibilitiesDoctorsSpecialty With {.DoctorSpecialtyID = si.ID, .RegDate = Date.Now}) PatientEligibilityObject.PatientsEligibilitiesDoctorsSpecialties.Add(PEDS)
HMSData.SubmitChanges()
it's worked fine and save record in Database with correct date
BUT
DoctorSpecialtyID
always saved with value 1
I solve it. the problem was in the relation between the tables.
The foreign key between PatientEligibilit and PatientsEligibilitiesDoctorsSpecialties
was not correct..