I encountered bug in my programm because of SubSonic3 returns records with default connection string in
SingleOrDefault(ByVal expression As System.Linq.Expressions.Expression(Of System.Func(Of Company.filter, Boolean)), ByVal connectionString As String, ByVal providerName As String)
In Subsonic sources, Database.cs line 323:
instance = Activator.CreateInstance<T>();
I think that was the cause of problem in my case. It creates instance with default constructor and then returns it as a result, that's where we loose custom connection string.
Personally I fixed it with adding 2 lines to ActiveRecord.tt template, in SingleOrDefault function, which has connectionString argument:
single._db=new <#=Namespace#>.<#=DatabaseName#>DB(connectionString, providerName);
single._repo = new SubSonicRepository<<#=tbl.ClassName#>>(single._db);
But I think you should examine this problem deeper, Rob :)
I don't follow. You specify the name of the ConnectionString is Settings.tt - that's the one we use.
Related
I am trying to make a simple calculator using SwiftUI, but one thing frustrates me. For reference, here is the minimum reproducible example:
#State var enteredNumber: String = "" // This is the user input in a string form
#State var usable number: Int = Int(enteredNumber) // I thought this would work but it doesn't.
I found this on hackingwithswift.com, and I thought it would work. I also looked my problem up in stack overflow, but I can't seem to understand any of the questions (I'm sorta new to SwiftUI). The approach I used just gave me an error saying:
Cannot use instance member 'enteredNumber' within property initializer; property initializers run before 'self' is available
and
Value of optional type 'Int?' must be unwrapped to a value of type 'Int'
Thanks in advance for your help!
Given that one can't subclass builtin types in Kotlin, I'm looking for a way to add special method functionality to specific types of string fields in a record, without applying those extension functions to all strings (even within that record type). Say, for example, I have some mutable string fields inside a record, for which I want to define special purpose behaviors.
class Customer {
// ...
var zipcode: String
var email: String
// ...
}
For zipcode, assume I'd like to be able to call
thisCustomer.zipcode.plusFour to get the +4 of the zip code (99999-9999) via regex.
For email, assume I'd like to be able to call
thisCustomer.email.domain to have a regex go get the ...#company.com
portion of the specified email.
My objectives are to:
Avoid the runtime overhead of boxing zipcode into a class Zipcode with just a
single var inside, given that the size of the Customer recordset could potentailly be millions.
Avoid the syntax of having to assign
thisCustomer.zipcode.value = "99999-9999" or thisCustomer.zipcode = Zipcode("99999-9999"), if I did end up having to box the string.
Avoid adding general String.plusFour and
String.domain extension properties, even just within the Customer
class... because zipcodes and emails could technically call each others'
extensions
I've been thinking this over and considered the following options, but struck out with each:
subclassing String: Not possible since strings (and all built-ins)
are closed
applying an interface Zip to the var declaration (var zipcode:
String, Zip): No such syntax I could find
adding inner functions within the getter itself: Syntax doesn't seem to exist for this
using objects or functions-within-functions: Couldn't think of a way
for this to work, although I might not be imaginative enough
Am I missing an obvious solution here? Even if not obvious, with all the syntactic magic of Kotlin, is there a way to make it happen? Maybe there's a way to accomplish some/all of the objectives above without using any of these approaches?
You can use type aliases to make the intention clear:
typealias ZipCode = String
val ZipCode.plusFour get() = ...
typealias Email = String
val Email.domain get() = ...
class Customer {
// ...
var zipcode: ZipCode
var email: Email
// ...
}
Unfortunately, this only clarifies intentions and doesn't stop the compiler from allowing zipcode.domain. But for now I don't think there is any way which satisfies both objectives 1 and 3.
Kotlin developers have decided not to support assignment-incompatible type aliases, which would have fit all your requirements, in favor of waiting for value classes to be available on JVM, as discussed in https://github.com/Kotlin/KEEP/issues/4.
You may create a decorator class using delegate:
class YourString(val value: String) : Comparable<String> by value, CharSequence by value {
val plusFour: String
get() = "" //your logic here
val domain: String
get() = "" //your logic here
override fun toString() = value
}
Usage:
fun String.toYourString() = YourString(this)
class Customer(var zipCode: YourString, var email: YourString)
val customer = Customer("+4 99999-9999".toYourString(), "xxx#company.com".toYourString())
println(customer.zipCode.plusFour)
println(customer.email.domain)
I originally had the following SQL function:
CREATE FUNCTION resolve_device(query JSONB) RETURNS JSONB...
and the following code calling the method generated by jOOQ:
final JsonArray jsonArray = jooqDWH.select(resolveDevice(queryJson)).fetchOne().value1().getAsJsonArray();
final JsonObject o = jsonArray.get(0).getAsJsonObject();
This worked fine. I needed to return a real device object rather than a JSON blob though, so I changed the SQL function to:
CREATE FUNCTION resolve_device(query JSONB) RETURNS SETOF device...
and the code to:
final ResolveDeviceRecord deviceRecord = jooqDWH.fetchOne(resolveDevice(queryJson));
but I am getting a runtime error:
org.jooq.exception.SQLDialectNotSupportedException: Type class com.google.gson.JsonElement is not supported in dialect DEFAULT
Many other parts of my code continue to work fine with the custom binding I have converting JsonElement to JSONB, but something about the change to this function's signature caused it to stop working.
I tried a few different variants of DSL.field() and DSL.val() to try to force it to be recognized but have not had any luck so far.
This could be a bug in jOOQ or a misconfiguration in your code generator. I'll update my answer once it is clear what went wrong.
Workaround:
Meanwhile, here's a workaround using plain SQL:
// Manually create a data type from your custom JSONB binding first:
final DataType<JsonObject> jsonb = SQLDataType.OTHER.asConvertedDataType(jsonBinding);
// Then, create an explicit bind variable using that data type:
final ResolveDeviceRecord deviceRecord =
jooqDWH.fetchOptional(table("resolve_device({0})", val(queryJson, jsonb)))
.map(r -> r.into(ResolveDeviceRecord.class))
.orElse(null);
I found the following comment on the Dapper .NET project home page.
Dapper supports varchar params, if you are executing a where clause on a varchar column using a param be sure to pass it in this way:
Query<Thing>("select * from Thing where Name = #Name", new {Name =
new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true });
On Sql Server it is crucial to use the unicode when querying unicode and ansi when querying non unicode
I'm evaluating Dapper for use with a legacy database (SQL Server 2008), with lots of stored procedures with varchar parameters, and I'm a little confused by this restriction.
With hand-crafted ADO.NET code, I'd use the following for the above query:
new SqlParameter("#Name", "abcde")
without specifying whether it's unicode or not, nor the length.
Why do I need this verbose DbString syntax with Dapper, specifying the column length, IsFixedLength and IsAnsi?
Why IsFixedLength = true for a varchar column (I'd expect it to be true for a char or nchar column)?
Do I have to use DbString like this for stored procedure parameters?
I was expecting Dapper to make my DAL code more concise, but this seems to be making it more verbose for varchar parameters.
UPDATE
I've researched a bit further, to try to understand why Dapper would have this varchar restriction, which I don't appear to have in my hand-crafted code, where I would normally create an input parameter as follows:
var parameter = factory.CreateParameter(); // Factory is a DbProviderFactory
parameter.Name = ...;
parameter.Value = ...;
and usually leave the provider to infer the DbType using its own rules, unless I specifically want to coerce it.
Looking at Dapper's DynamicParameters class, it has a method AddParameters which creates parameters as follows:
var dbType = param.DbType; // Get dbType and value
var val = param.Value; // from
...
// Coerce dbType to a non-null value if val is not null !!!!!
if (dbType == null && val != null) dbType = SqlMapper.LookupDbType(val.GetType(),name);
...
var p = command.CreateParameter();
...
if (dbType != null)
{
p.DbType = dbType.Value;
}
I.e. it explicitly coerces IDataParameter.DbType to a value it looks up with its own algorithm, rather than leaving the provider to use its own rules.
Is there a good reason for this? It seems wrong for me, particularly in the light of the comment about Dapper's support for varchar parameters.
You need this syntax when working with ODBC.
You would need to define a CHAR(30) field as a DbString in c# for Dapper and also set the length (30) and ansi (true) values to prevent Dapper from assuming the string was a text/blob type. Otherwise you will likely receive the error: "Illegal attempt to convert Text/Byte blob type".
I was getting this error using ODBC to connect to Informix until I defined my param as a DbString() and set the length and ansi values.
More info here.
var param = new { Varchar1 = "", Varchar2 = "" };
db.Query("SP", param, commandType:CommandType.StoredProcedure);
In SubSonic, version 2.2, the following (MSSQL-specific) code fails:
SqlQuery update =
new Update(SomeTable)
.SetExpression(SomeTable.SomeDateTimeColumn).IsEqualTo("GETDATE()")
.Where(SomeTable.IdColumn).IsEqualTo(id);
At this point update.ToString() produces a perfectly legal SQL sentence:
UPDATE [dbo].[SomeTable] SET [SomeDateTime]=GETDATE()
WHERE [dbo].[SomeTable].[ID] = #ID0
update.Execute() however fails with:
{"Failed to convert parameter value from a String to a DateTime."}
at SubSonic.Update.Execute()
Is there any possibility to use sql server functions in expressions?
Ok, I've found a workaround - it is possible to use SQL Server functions outside of InlineQuery. The trick is that you must not use "strongly typed" version of SetExpression that uses TableColumn parameter, but pass column name strings, like this:
SqlQuery update =
new Update(SomeTable)
.SetExpression(SomeTable.Columns.SomeDateTime).IsEqualTo("GETDATE()")
.Where(SomeTable.IdColumn).IsEqualTo(id);
The important part being: SomeTable.Columns.SomeDateTime instead of SomeTable.SomeDateTimeColumn.
For the specific example you've posted you could just do the following:
SqlQuery update = new Update(SomeTable)
.SetExpression(SomeTable.SomeDateTimeColumn).IsEqualTo(DateTime.Now)
.Where(SomeTable.IdColumn).IsEqualTo(id);