how about run Subsonic version 2 and 3 together? - subsonic

Today I compile subsonic version with different namespace (as subsonic3) and place it together with subsonic version 2.
Also create all files (for both versions, in different dlls) for my database with success, and make simple tests, and seams that everything works perfect.
This is my simple test code, and you can see 3 and 2 run together.
var PageTitlesOn3 = from p in ATH_Store_Product.All()
where p.ProductID == 1
select p;
foreach (ATH_Store_Product Ena in PageTitlesOn3)
{
txtOnMe.Text += string.Format("<br />{0} ) {1}",
Ena.ProductID, Ena.ProductName);
}
AthStoreProductCollection AllMyTitlesAgainOn2 = new AthStoreProductCollection()
.Where(AthStoreProduct.Columns.ProductID, 1)
.Load();
foreach (AthStoreProduct Ena in AllMyTitlesAgainOn2)
{
txtOnMe.Text += string.Format("<br />{0} ) {1}",
Ena.ProductID, Ena.ProductName);
}
I did that, because I like to move to subsonic 3, but I need to do that one piece at the time, some part code, then some other part etc.
My project is a little bit huge, and run online, and I do not won't to stop it run.
This way, placing subsonic 2 and 3, working together, I can start migrating my code in time.
Now my question is if I am doing any big error, and if they going to crash after run together all their time, if I eat a lot of resources, etc.
I have looked the source code of subsonic, but I am not that familiar (yet) with what really do, what and how is open the database etc…
Now, my second question is, why not subsonic ver3, permanently renamed to subsonic3, and other users do the same think that I did.
Thank you in advanced.

I can't see anything wrong here, after all, it is as if you have two DAL's, one of which it tends to disappear in favor of the other.

Related

Jooq database/schema name mapping

I use jooq to generate objects against a local database, but when running "for real" later in production the actual databases will have different names. To remedy this I use the <outputSchemaToDefault>true</outputSchemaToDefault> config option (maven).
At the same time, we have multiple databases (schemas), and are using a connection pool to the server like "jdbc:mysql://localhost:3306/" (without specifying a database here).
How do I tell jooq which database to use when running queries?
I have tried all config I can think of:
new Settings()
.withRenderSchema(true) // true/false seems to make no difference.
.withRenderCatalog(true) // true/false seems to make no difference.
.withRenderMapping(new RenderMapping()
.withDefaultSchema("my_database") // Seems to have no effect.
// The above 3 configs always give me an error saying "no database selected".
// Adding this gives me 'my_database.my_table' does not exist - while it actually does.
.withSchemata(new MappedSchema()
.withInputExpression(Pattern.compile(".*"))
.withOutput("my_database")
));
I have also tried using a database/schema name, as in not configuring outputSchemaToDefault. But then, adding the MappedSchema code above, but that gives me errors with "'my_databasemy_database.my_table' does not exist", which is correct. I have no clue why that code gives me the database/schema name twice?
Edit:
When jooq tells me that the db.table does not exist, if I put a break point in a good place and get the sql from jooq and run exactly that against my database it does work. But jooq fails to run it.
Also, I'm using version 3.15.3 of jooq.
I solved it. Instead of using .withInputExpression(Pattern.compile(".*")), it seems to work with .withInput("").
I'm still not sure why it works, or if this is the "correct" way of solving it. But at least it is a way forward.
No clue why using the pattern, I got the name twice though. But that one I'll leave alone.

Automating/Tracking Knex Migrations and Lucid Models

The Situation
I recently started working on a new project using nodejs. I have a background of using Python/Django and C#/.NET (not a huge fan of the latter). Node is awesome, but I must say I miss the ease of building models and automating migrations in Django. I am currently using the AdonisJS framework which leverages Knex. Knex is a powerful library, but the migrations all need to be manually built. Additionally, the AdonisJS ORM that manages the Models is independent of Knex (migration manager). You also do not define field attributes on the Models, which can have benifits for dynamically doing things in the front and back end. All things considered, there is a lot of room for human error, miscommunication and a boat load more typing required. I know the the hot thing these days is to keep it loose and fast, but for this specific project, I am looking for a bit more structure than loosely defined models.
Current State
What I have landed on is building a new Class called tableModel and a field class to define the fields within table model. I have already completed this and I am successfully writing the migration files leveraging mustache. I plan on also automatically writing the Models which I shouldn't have a problem with (fingers crossed).
The Problem
Here is where it gets a little tough and where I need help...I need to track what has been added or removed via migration so I can effectively write ups and downs as the tableModels change over time.
So let's say I add a "tableModel" which creates a migration to create table Foo with fields {id (bigint), user_id(int), name(string255)}
Later I want to add a field called description so I would simply add it to my "tableModel" and then run a build command which would build out the migration.
How do I check what has already been created though so I only do an up() for description?
Then I want to remove the name field so I mark it out in my "tableModel" and run a build migration command. How do I check what has been migrated that now needs to be added in to the down().
Edit: I would add a remove field to the up and the corresponding roll back to the down.
Bonus Round
Let's say I want to change user_id from an int to a bigint, because who makes a foreign key just an int? How do I check not just what needs to be added to the up and down, but also checks if I need to change a property on a field.
Edit: would just write the up. and a corresponding roll back to the down
The Big Question
Basically, how do I define dirty "tableModels" classes
Possible Solution?
I am thinking that maybe I should capture some type of registry or snapshot and then run the comparison when building the migrations and or models, then recapture/snapshot. If this is the route, should I store in a json file, write this to the DB itself, or is there another/better option.
If I create the tableModel instances as constants, could I actually write back to the JS file and capture the snapshot as an attribute? IF this is an option, is Node's file system the way to go and what's the best way to do this? Node keep suprising me so I wouldn't be baffled if any of these are an option.
Help!
If anyone has gone down this path before or knows of any tools I could leverage, I would greatly appreciate it and thank you in advance. Also, if I am headed in a completely wrong direction, then please let me know, I both handle and appreciate all types of feedback.
Example
Something to note, when I define the "tableModel" for a given migration or model, it is an instance of the class, I am not creating an extended class since this is not my orm.
class tableModel {
constructor(tableName, modelName = tableName, fields = []) {
this.tableName = tableName
this.modelName = modelName
this.fields = fields
}
// Bunch of other stuff
}
fooTableModel = new tableModel('fooTable', 'fooModel', fields = [
new tableField.stringField('title'),
new tableField.bigIntField('related_user_id'),
new tableField.textField('description','Testing Default',false,true)
]
)
which equates to:
tableModel {
tableName: 'fooTable',
modelName: 'fooModel',
fields:
[ stringField {
name: 'title',
type: 'string',
_unique: false,
allow_null: null,
fieldAttributes: {},
default_value: null },
bigIntField {
name: 'related_user_id',
type: 'bigInteger',
_unique: false,
allow_null: null,
fieldAttributes: {},
default_value: 0 },
textField {
name: 'description',
type: 'text',
_unique: false,
allow_null: true,
fieldAttributes: {},
default_value: 'Testing Default' } ]
You have the up and down notation mixed up. Those are for migrating the "latest" (runs the up function) and doing rollbacks (runs the down function). Up and down to not relate to dropping or adding table columns.
The migrations up is for any change, and the down is to reverse those changes. So if you wanted to drop a column from some table, you write the command in the up, then write the opposite in the down (you'd add it back in...), such that you can "rollback" and the change is effectively reversed. You have to be careful with such things though, as you can put yourself in a situation where you actually lose data.
Want to add a column? Write it in the up, and drop the column in the down.
One of the major points behind the migrations mechanism is to track the state of changes of your database, as time goes forward. So generally, if you created a table in some migration, then a day or so later you realize you need to drop/add columns, you normally don't go back and edit the existing migration, especially if the migration has already been run. You'd just write a new migration to drop/add your column.
Since you're using knex, there are a couple "knex" tables that get created. By default the one you're looking for is knex_migrations, unless someone specifically modified the settings to change the name of it. This table holds all the migrations that have run against your DB, per batch. From the CLI, assuming you have knex.js installed globally, you can run knex migrate:latest, and that will push all the migrations that exist in your directory to the target database, if they have not yet been run. It does this by way of examining that knex_migrations table. If you roll a change and don't like it, and assuming you've properly done the down function, you can invoke knex migrate:rollback to reverse the change. If there are 3 migration files that have NOT yet been run, invoking knex migrate:latest will run all 3 of those migration files under a new batch #, which is 1 higher than the most recent batch number. Conversely, if you invoke a knex migrate:rollback, it will find the highest batch number (there could be more than 1 migration in a batch...), and invoke the down function on all those files, effectively rollback those changes.
All that said, knex is a "query builder" tool. It's got a ton of helper functions to help build the sql for you. Personally, I find this to be a major distraction. Why spend hours on hours figuring out all the helper functions when I can just go crank out raw SQL and run that. Thus, that's what we've done in our system. we use knex.raw('') and write our own DDL and DML. It works great and does exactly what we need it to. We don't need to go figure out the magic of the query building.
The short answer is that knex will automatically know what has and has not been run for you (again, via that knex_migrations table it creates for you...).
Things can get weird though when it start involving git and different branches. I recommend that if you're writing migrations on some branch, and you need to go do other work, always remember to first perform a rollback of any migrations you've done in that branch BEFORE switching branches. Otherwise you will be in weird DB states that don't coincide with the application code.
I would personally just deal with updating models independently of writing migrations. For example, if I'm adding a description column to some table, then I probably want to manually update the ORM to reflect the change of the new db schema. Generally, I've found trying to use a tool that automagically does that for you (rather, if I change the orm, stuff happens to write all the underlying sql...) usually winds me up in a heap of trouble and I just spend more time trying to un-fudge stuff. But, that's just my 2 cents :)
Here is where it gets a little tough and where I need help...I need to track what has been added or removed via migration so I can effectively write ups and downs as the tableModels change over time.
You could store changes in a DB/txt file and those can act as snapshots. So when you want to rollback to a particular migration, you would find the changes (up/down) made for that mutation and adjust accordingly.
Later I want to add a field called description so I would simply add it to my "tableModel" and then run a build command which would build out the migration. How do I check what has already been created though so I only do an up() for description?
Here you either call the database itself directly and check what fields have already been created. If a field is already their and the attributes are the same, you can either ignore it or stop the transaction all together.
Bonus Round Let's say I want to change user_id from an int to a bigint, because who makes a foreign key just an int? How do I check not just what needs to be added to the up and down, but also checks if I need to change a property on a field.
Again, call the DB itself on the table in question. I know the SQL call would be:
describe [table_name];
After reading the end, I think you answered this yourself, but I think capturing these changes would work best in a NoSql database since you're using Node or PostGres with it's json field.

How do you correctly update a model in Xcode4 without corrupting it?

I never had any problems with Xcode3, but with Xcode4 I'm getting Apple's code failing approx 1 time in 3 when I update a core data model, with the dreaded "Persistent store migration failed, missing source managed object model." error.
Here's my setup (how I configured the project to auto-migrate):
NSPersistentDocument, from Apple's template
Override Apple's model-loading method, and the ONLY thing I do is to provide the two flags in the storeOptions Dictionary, which turn on auto-migration
-(BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newOptions = nil;
if( storeOptions != nil )
newOptions = [NSMutableDictionary dictionaryWithDictionary:storeOptions];
else
newOptions = [NSMutableDictionary dictionary];
[newOptions setValue:#"YES" forKey:NSMigratePersistentStoresAutomaticallyOption];
[newOptions setValue:#"TRUE" forKey:NSInferMappingModelAutomaticallyOption];
BOOL success = FALSE;
success = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newOptions error:error];
return success;
}
Here's the process I've been using (which is already working around 1 bug in Xcode4!)
Select the model (named "something.xcdatamodel" in Xcode4, with a twisty on the left)
Go to Editor menu, select "Add new model version..."
Name the new version 1 integer higher than last - e.g. if previous was "4" name the new one "5"
In the right-hand pane, change the current model version to the newly-created one
workaround for XCode4 bug: select any file, then select the newly-created model. If you do not, Xcode shows the selection on the newly-created model, but will edit the previous model instead, which definitely corrupts everything in CoreData
Edit your model; in this case, I'm adding a new attribute to an existing entity
Save. Build. Run. ... CRASH.
Except, as I said, approx 2 times in 3 this works correctly. Once it works once, it's (obviously) fine - the lightweight migration is complete, the next save saves in the new model version.
So I'm guessing there's something I'm doing wrong in the above steps, but I've been through the docs 5 or 6 times and can't see anything obvious. Doesn't help that NSPersistentDocument docs are all out of date - but I've done lightweight migration on iPhone lots of times too, so I'm reasonably confident with doing this, and it seems right to me.
Other things I've tried/checked:
- iPhone Core Data Lightweight Migration Cocoa error 134130: Can't find model for source store (nope; only the root xcdatamodel was being included)
Use [NSNumber numberWithBool:YES] not #"YES" or #"TRUE".
Since you have eliminated a corrupt development store as a source of the problem, I suspect the problem lays in Xcode 4.x which is buggy to say the least. A lot of people are reporting similar issues but no two problems seem exactly the same. It is probably a bug/s that only occur with specific data model setups so the problem will be very hard to track down.
You may simply have to abandon automatic migration and create an explicit migration map. It takes longer and introduces complexity into your code but it will always work.
If you have a shipping app and will be dealing with end user data in the wild, you do have a moral and business obligation to take the extra step to protect end user data.
I was getting super-confused but this, and it WASN'T working.. because I was assuming that the method would already HAVE a "store options" dictionary.. I just needed to check for it's existence before i set the aforementioned options…
-(BOOL)configurePersistentStoreCoordinatorForURL: (NSURL*)u
ofType: (NSString*)t
modelConfiguration: (NSString*)c
storeOptions:(NSDictionary*)o
error: (NSError**)e
{
return [super configurePersistentStoreCoordinatorForURL:u
ofType:t
modelConfiguration:c
storeOptions:
o ? [o dictionaryWithValuesForKeys:
#[ NSMigratePersistentStoresAutomaticallyOption, #YES,
NSInferMappingModelAutomaticallyOption, #YES]]
: #{ NSMigratePersistentStoresAutomaticallyOption :#YES,
NSInferMappingModelAutomaticallyOption :#YES}
error:e];
}

subsonic query problem

I'm using subsonic 2.2 in an app. I'm running a little complicated query in I have used both "And" and "Or" for a field, I'm little confused about how it is going to be translated into sql statement
MytableCollection col = DB.Select().From("mytable").Where("prop1").IsEqualTo(obj.prop1)
.And("prop2").IsEqualTo(obj.prop2)
.And("prop3").IsEqualTo(obj.prop3)
.Or("prop1").IsEqualTo(1)
.ExecuteAsCollection<MytableCollection>();
I want to perform query like this.
select * from mytable where (prop1=obj.prop1 or prop1=1) and prop2=obj.prop2 and prop23=obj.prop3
As Andra says you can use AndExpression. This should do what you want:
MytableCollection col = DB.Select().From(Mytable.Schema)
.Where(Mytable.Columns.Prop2).IsEqualTo(obj.prop2)
.And(Mytable.Columns.Prop3).IsEqualTo(obj.prop3)
.AndExpression(Mytable.Columns.Prop1).IsEqualTo(obj.prop1)
.Or(Mytable.Columns.Prop1).IsEqualTo(1)
.ExecuteAsCollection<MytableCollection>();
N.B. using MyTable.Schema and MyTable.Columns will catch a lot of issues at compile time if you rename tablees and will save errors caused by mistyping
Something that is REALLY useful to know about is also the following two methods to call in your query building:
.OpenExpression()
and
.CloseExpression()
Mix those bad buoys and you have a lot better control over knowing where things start and finish
you can use expression in subsonic 2.2.
MytableCollection col = new Select(Mytable.Schema)
.WhereExpression("prop1").IsEqualTo(obj.prop1).Or("prop1").IsEqualTo(1)
.AndExpression("prop2").IsEqualTo(obj.prop2)
.AndExpression("prop3").IsEqualTo(obj.prop3)
.ExecuteAsCollection<MytableCollection>();

Subsonic : Same column name different tables

I have a query where I need to do a "Where" clause for two different columns in two different tables but subsonic creates the same parametrized parameter name for both which is causing an issue. How can I fix this?
string _RawSql = new Select()
.From(Tables.Table1)
.InnerJoin(Tables.Table2)
.InnerJoin(Table3.SidColumn, Table2.Table3SidColumn)
.Where(Table1.SidColumn).IsEqualTo(2)
.And(Table3.SidColumn).IsEqualTo(1)
.BuildSqlStatement();
The query this is creating is
SELECT ....
FROM [dbo].[Table1]
INNER JOIN [dbo].[Table2] ON [dbo].[Table1].[Table2Sid] = [dbo].[Table2].[Sid]
INNER JOIN [dbo].[Table3] ON [dbo].[Table2].[Table3Sid] = [dbo].[Table3].[Sid]
WHERE [dbo].[Table1].[Sid] = #Sid
AND [dbo].[Table3].[Sid] = #Sid
Note that in the last two lines its using #Sid for both Table1 and Table3. How go I do it so it uses #Sid0 and #Sid1?
Any help would be appreciated. Thanks
Thanks for the response, I really appreciate it. I am using 2.1
I am already using TableColumn. Below is the c# subsonic code...
.Where(Table1.SidColumn).IsEqualTo(2)
.And(Table3.SidColumn).IsEqualTo(1)
which creates the following sql when viewed in sql profiler
WHERE [dbo].[Table1].[Sid] = #Sid
AND [dbo].[Table3].[Sid] = #Sid
Could you please show me how can I replace these lines with the way you are suggesting? I would really rather not use literal "Table2.Sid = 2"
ranmore, the issue is same with variables or with constants.
I have even tried
.Where("Table1.Sid").IsEqualTo(2)
.And("Table3.Sid").IsEqualTo(1)
This creates the query as
WHERE Table1.Sid = #Table1.Sid0
AND Table3.Sid = #Table3.Sid1
I finally get different parametrized vars in this case but now SQL Server complains because it does not like . in the parametrized var names.
I have no clue how to perform a join with 2 where clauses for 2 different tables!
What version are you using? In 2.2 You can use the TableColumn object to get around this (it may be the same for 2.1 as well. So instead of using the struct, as you're doing, you can use the object (Table2.SidColumn).
If push comes to shove - you can override everything with a string - so in your case you could use "Table1.Sid" and "Table2.Sid" right in the Where() method.
I haven't been able to confirm this, but perhaps the problem only happens with literals? (not sure if your sample code is like that for brevity's sake)
int table1SidColumnValue = 2;
int table3SidColumnValue = 1;
.Where(Table1.SidColumn).IsEqualTo(table1SidColumnValue)
.And(Table3.SidColumn).IsEqualTo(table2SidColumnValue)
I remember seeing a problem with this when using multiple .In() clauses with literal values, not sure if that applies to your problem though.
I'm not sure what version of the code I have but your query produces numbered parameters for me.
If you look at Line 255 of ANSISqlGenerator.cs
https://github.com/subsonic/SubSonic-2.0/blob/master/SubSonic/SqlQuery/SqlGenerators/ANSISqlGenerator.cs
c.ParameterName = String.Concat(col.ParameterName, query.Constraints.IndexOf(c));
The where parameters really should have numbers appended to them... maybe pull the latest version?

Resources