Define unique constraint in Fluent Migrator - fluent-migrator

I'm trying to create a unique column using Fluent Migrator. However, it doesn't work if I try to define the unique constraint together with the column definition, like e.g.:
[Migration(20120404190455)]
public class Migration1 : Migration
{
public override void Up()
{
Create.Table("Test")
.WithColumn("Name").AsString(64).Unique();
}
public override void Down()
{
Delete.Table("Test");
}
}
I execute the migration like this:
<sourcedir>\packages\FluentMigrator.Tools.1.0.1.0\tools\AnyCPU\40\Migrate.exe -a build\TheMigrationDLL.dll --db sqlserver2008 -conn "DQLEXPRESS;Initial Catalog=DBNAME;Trusted_Connection=True;" --verbose=true
Output:
connection is null!
connection is null!
Using Database sqlserver2008 and Connection String Data Source=.\SQLEXPRESS;Initial Catalog=DBNAME;Trusted_Connection=True;
-- VersionMigration: migrating ===============================================
-- CreateTable VersionInfo
CREATE TABLE [dbo].[VersionInfo] ([Version] BIGINT NOT NULL)
-- -> 0,0170009s
-- VersionMigration: migrated
-- -> 0,0190011s
-- Migration1: migrating =====================================================
-- CreateTable Test
CREATE TABLE [dbo].[Test] ([Name] NVARCHAR(64) NOT NULL)
-- -> 0,0020002s
-- Migration1: migrated
-- -> 0,0030002s
INSERT INTO [dbo].[VersionInfo] ([Version]) VALUES (20120404190455)
-- Committing Transaction
Obviously no unique index is created. However, if I create the index in a stand-alone call:
Create.Index().OnTable("Test")
.OnColumn("Name").Ascending()
.WithOptions().Unique();
Output:
....
-- CreateIndex Test (Name)
CREATE UNIQUE INDEX [IX_Test_Name] ON [dbo].[Test] ([Name] ASC)
....
I found several issues on github regarding this (e.g. #49 and #83) but they have been closed with reference to this pull.
I wonder if I'm using the wrong version. I'm using version 1.0.1.0 as available from NuGet.
I'd appreciate hints on what I'm doing wrong here. Thanks in advance!
Regards,
Andre

FluentMigrator 1.0.2.0 solves this particular problem, please update your package.
FluentMigrator 1.0.1.0 was released september 2011, as of yesterday we are back on track with releasing.
Remember if you have a .NET 4 migration assembly to get the fluentmigrator.tools package as well, so you have the right version of the Migrate.exe version.

Related

Flyway reports success even though database gave warnings

We are using Flyway 4 (great tool!) on Oracle.
When invalid DDL is committed, the continuous database build breaks.. and all the team gets an email.. all good so far.
But when, code that breaks one of our stored procedures is committed.. ie procedure gets created, but it fails to compile.. we still get a successful migration reported from Flyway.
During the migration we see something like :
DB: Warning: execution completed with warning (SQL State: 99999 - Error Code: 17110)
..but still the Flyway ant task reports success.
As we have a lot of stored procedures, 9 times out of 10 it is these that are broken by developers, and not the DDL. We really would like Flyway to fail on a warning also. Can anyone advise how best to approach this?
Solved! Found an acceptable solution for us and implemented it as follows, utilising Flyways callback mechanism which is documented on the Flyway website.
There are many callbacks available and are invoked at various points, but the one that appears to suit our needs is afterMigrate. In the callback, we can execute sql (on Oracle) which counts the number of invalid objects in the user schema at hand
So, implementing a java afterMigrate callback as follows does the job:
public void afterMigrate(Connection connection) {
String countInvalidObjs = "select count(*) " +
"from user_objects " +
"where object_type in ('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY','TRIGGER') " +
"and status = 'INVALID' ";
int invalidObjCount = -1;
Statement statement;
try {
statement = connection.createStatement();
ResultSet rs = statement.executeQuery(countInvalidObjs);
while (rs.next()) {
invalidObjCount = rs.getInt(1);
}
} catch(Throwable t) {
System.out.println("*error* " + t.getMessage());
} finally {
if(invalidObjCount!=0) {
throw new IllegalArgumentException("fail to complete migration, build finished with databse warnings");
}
}
}

NHibernate: adding calculated field to query results

I have inherited an ASP.NET website built on NHibernate, with which I have no experience. I need to add a calculated field based on a column in a related table to an existing query. In SQL, this would be done easily enough using a correlated subquery:
select
field1,
field2,
(select count(field3) from table2 where table2.table1ID = table1.ID) calc_field
from
table1
where
[criteria...]
Unfortunately, of course, I can't use SQL for this. So in reality, I have three related questions:
What is the best way to trace through the web of interfaces, base classes, etc used by NHibernate in order to pinpoint the object where I need to add the field?
Having located that object, what, if anything, has to be done besides adding a public property to the object corresponding to the new field?
Are there any NHibernate-specific considerations with regard to referencing a related object in a query?
Here is the existing code that performs the search:
public INHibernateQueryable<C> Search(ISearchQuery query, string sortField)
{
_session = GetSession();
var c = _session.Linq<C>();
c.Expand("IP");
c.Expand("LL");
c.Expand("LL.Address");
c.Expand("LL.Address.City");
c.Expand("LL.Address.City.State");
c.Expand("LL.Address.City.County");
c.Expand("CE");
c.Expand("IC");
c.Expand("AR");
c.Expand("ER");
c.Expand("Status");
var res = _SearchFilters
.Where(x => x.ShouldApply(query))
.Aggregate(c, (candidates, filter) => (INHibernateQueryable<C>) filter.Filter(candidates, query));
res = SortSearch(res, sortField);
return res;
}
I appreciate any advice from experienced Hibernators.
Thanks,
Mike
If you are only interested in returning a query containing a computed value, you can still call a stored procedure in NHibernate and map the results to a POCO in the same way as you map a table for CRUD operations; obviously read-only instead of updatable.
Have a look at the ISession.CreateSQLQuery method; I can post an example from one of my projects if you need one.

SQLite CreateTable<> Database that already exists is replaced

Database that already exists is replaced by calling the method CreateTable <> in SQLite for Windows 8, erasing all the lines and creating a new table. How can I solve? following code to analyze:
using(var db = new SQLite.SQLiteConnection(App.DBPath))
{
db.CreateTable<ListasEntid>();
if (db.ExecuteScalar<int>("select count(1) from ListasEntid")==0)
{
db.RunInTransaction(() =>
{
db.Insert(new ListasEntid() { Nome = "Lista", Eletros = "Teste" });
});
}
}
Not sure what language you are using, but if you can execute raw SQL then you can use the following syntax:
CREATE TABLE IF NOT EXISTS ListasEntid (nome text, eletros text);
This ensures that table ListasEntid exists without nuking any of your previous data.
Thank you for the attention, but the problem was not specifically CreateTable method, but in the application configuration in the application properties, Debug tab, in option start the box was marked, "Unistall and then re-install my packege", erasing all files always initializing the debug.

Error inserting data into SQL Server database with foreign key in ASP.NET (could not find primary key)

I am using ASP.NET MVC2 in Visual Studio 2008. I believe the SQL Server is 2005.
I have two tables: EquipmentInventory and EquipmentRequested
EquipmentInventory has a primary key
of sCode
EquipmentRequested has a
foreign key called sCode based upon
sCode in EquipmentInventory.
I am trying the following code (lots of non-relevent code removed):
try
{
EChODatabaseConnection myDB = new EChODatabaseConnection();
//this section of code works fine. The data shows up in the database as expected
foreach (var equip in oldData.RequestList)
{
if (equip.iCount > 0)
{
dbEquipmentInventory dumbEquip = new dbEquipmentInventory();
dumbEquip.sCode = equip.sCodePrefix + newRequest.iRequestID + oldData.sRequestor;
myDB.AddTodbEquipmentInventorySet(dumbEquip);
}
}
myDB.SaveChanges(); //save this out immediately so we can add in new requests
//this code runs fine
foreach (var equip in oldData.RequestList)
{
if (equip.iCount > 0)
{
dbEquipmentRequested reqEquip = new dbEquipmentRequested();
reqEquip.sCode = equip.sCodePrefix + newRequest.iRequestID + oldData.sRequestor;
myDB.AddTodbEquipmentRequestedSet(reqEquip);
}
}
//but when I try to save the above result, I get an error
myDB.SaveChanges();
oldData is passed into the function. newRequest is the result of adding to a "non-related" table. newRequest.iRequestID does have a value.
In looking at the reqEquip is the watch window, I do notice that EquipInventory is null.
The error message I receive is:
"Entities in 'EChODatabaseConnection.dbEquipmentRequestedSet' participate in the 'FK_EquipmentRequested_EquipmentInventory_sCode' relationship. 0 related 'EquipmentInventory' were found. 1 'EquipmentInventory' is expected."
Obviously I'm doing something wrong but thus far, I can not seem to find where I am having a problem.
Anyone have some hints on how to properly insert a record into a table that has a foreign key reference?
UPDATE:
I am using the Data Entity Framework.
UPDATE:
Thanks to Rob's answer, I was able to figure out my error.
As Rob mentioned, I needed to set my reference for the foreign key.
My coding result looks like:
foreach (var equip in oldData.RequestList)
{
if (equip.iCount > 0)
{
dbEquipmentInventory dumbEquip = new dbEquipmentInventory();
dumbEquip.sCode = equip.sCodePrefix + newRequest.iRequestID + oldData.sRequestor;
myDB.AddTodbEquipmentInventorySet(dumbEquip);
//add in our actual request items
dbEquipmentRequested reqEquip = new dbEquipmentRequested();
reqEquip.EquipmentInventory = dumbEquip;
myDB.AddTodbEquipmentRequestedSet(reqEquip);
}
}
myDB.SaveChanges();
Does anyone see a better method for doing this?
What are you using as an ORM? I believe that regardless of which one you're using, you could use the foreign key handling of most ORMs to handle this for you. For example, you make a new dumbEquip, don't do the immediate save. Do your dbEquipmentRequested reqEquip = new dbEquipmentRequested(); and add the data to it and then say dumbEquip.dbEquipmentRequested.Add(reqEquip). Then save the record and the ORM should save the records in the correct order required for the FK and even enter the FK ID into the reqEquip record.

How to return multi-table join value from BLL

This question is regarding the ASP.NET webservice that i am creating using the DAL-BLL architecture for my final school project.
I have a stored procedure, which is a select query with an inner join for 2 tables. Hence the stored procedure returns multi-table value. One of my DAL tableAdapter methods accesses this stored procedure. How do i retrieve the return value in the BLL? Do i have to create a class structure similar to the one supposed to be returned by the stored proc? or is there a direct way to achieve the same? Help greatly appreciated. Please let me know if someone needs code applet to get a better understanding. Thanks
Here is some more information:
I am using the SQL dataset (.xsd) in DAL. So i have a datatable called "Insurance", which has a tableAdapter. One of the queries in the adapter references to a stored procedure, which has an inner join. So my SP looks like:
ALTER PROCEDURE dbo.GetInsurancesPaged
(
#startRowIndex int,
#maximumRows int,
#patientID int
)
AS
select * from
(
SELECT Insurance.insuranceID, Insurance.memberID, Insurance.groupID, Insurance.accountType, Insurance.comments, Insurance.patient, Insurance.company, InsuranceCompany.companyID, InsuranceCompany.companyName, InsuranceCompany.address, InsuranceCompany.phone, InsuranceCompany.fax, ROW_NUMBER() over (order by Insurance.dateModified DESC) as ROWRANK
FROM Insurance INNER JOIN InsuranceCompany ON Insurance.company = InsuranceCompany.companyID
WHERE Insurance.patient = #patientID
)
AS DataWithRowNumbers
WHERE ROWRANK > #startRowIndex AND ROWRANK <= (#startRowIndex + #maximumRows)
So this SP returns a datatable which will be a combination of the 2 tables in the inner join. Please correct me if i am wrong.
Now in my BLL, i have:
[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
public mySys.InsuranceDataTable GetInsurancesPaged(int startRowIndex, int maximumRows, int patientID)
{
return insAdapter.GetInsurancesPaged(startRowIndex, maximumRows, patientID);
}
where insAdapter is an instance of insuranceTableAdapter
This gives an error on execution. I can execute the SP successfully, so i think the problem is only bcz i am trying to return a wrong datatable from the BLL.
Please help me solve this.
If using ADO .Net dataset. The wizard will definetly create a table for the same. now from the dataaccess layer, do the following steps
1. Create a object of dataset. (DLL)
Private YourCustomeDataSetDatatable DataAccess()
{
YourCustomDataSet ds = new YourCustomDataSet(); // also called strongly typed dataset
YourCustomeDataSetDatatable dt = ds.YourCustomeDataSetDatatable ()
YourCustomeDataSetTableAdapter ta = new ds.YourCustomeDataSetTableAdapter (); // table adapter that will be invoked
ta.Fill(dt); // or if you have set to return only you can also use GetData()
}
2. Now in business layer
Private YourCustomeDataSetDatatable DataAccess()
{
// create a object of DLL.
MyDAL myDal = new MyDAL ();
return myDal.DataAccess();
}
Catch this on your UI page by following the creating object of BLL and call the method. Here in BLL you can also do various operations to lowered the codes in you ui and keeping it clean from various manipulations.
Found a solution :)
Finally got it working.
I created a new table adapter using the Dataset designer, and called the SP as one of the queries there. The datatable thus created, has all the fields (from Insurance and InsuranceCompany) included. Now, ASP.NET can detect that the return type is the newly created datatable.
Works like a charm.
If there is a better way to solve this, please comment.
Thank you all for your time.

Resources