Since most of the projects I work on are exclusively SQL Server 2005/2008 database driver, I was wondering about the implications of using System.Data.SqlTypes classes as data types in my VB.Net Framework 4.0 code. For example currently I define integer variables as
Dim X as Integer
Using System.Data.SqlType classes I would define my intege variables as
Dim X as System.Data.SqlTypes.SqlInt32
Please comment on the implications for performance, serialization and databinding. One difference would be that all variables would default to Null.
I don't think there's a lot of problems with the idea, serialization and databindinding should work, and I wouldn't worry about performance unitl it's an issue.
But while it would work, I don't think it's a good design. You will end up using sqltypes in areas that have nothing to do with sql. Other than as parameters to sql commands, sqltypes have no advantage over nullables, which are more generic.
Its a bad idea because if someday you need to migrate from sql server to another database you will have to change all the vars in your code to the right type. (And all the castings, etc...)
Also, if you need null variables you can always use
Dim x As Nullable(Of Integer)
Also, for exaple integers are inmutable value types iso reference types like SqlInt32 and are much more optimized.
Value types vs reference:
http://msdn.microsoft.com/en-us/library/t63sy5hs%28v=vs.80%29.aspx
What is the difference between a reference type and value type in c#?
So probably SqlTypes will be slower and also will force you to stay forever on sqlserver.
Also consider that these types are not available for all the framework versions, and your code could be in some situations not very reusable, just for using these data types.
Related
I write many Maximo Where Clauses (which use Oracle SQL), and save them as public queries.
I encourage others to edit/customize the work I share with them.
But when my query uses the same string throughout it many times, it's tedious to make sure all instances are replaced. It's not like there's a built-in find-replace tool or anything.
Is there a way to define a custom string variable at the beginning, and reuse that variable many times thoughout the where clause?
No, you can't do that. But what you could do is make a relationship from your parent object to a system property / maxpropvalue child object where propname = 'company.app.varname. Then, you can use the System Properties app to change the value of the variable for all references. And you can make a reference to it in your query using standard :relationshiptomaxpropvalue.propvalue syntax.
HTH.
Using the SQL type provider in FSharp.Data with MSFT SQL Server, I declare the type:
type dbSchema = FSharp.Data.TypeProviders.SqlDataConnection<"Data Source=DESKTOP-5\SQLEXPRESS;Initial Catalog=Data;Integrated Security=True;MultipleActiveResultSets=True;">
outside of any module, along with most of my other types (following a suggestion to declare types outside of modules to avoid nested classes). I really wouldn't know, but assume that it's so far so good.
Where I'm wondering how to arrange things is in using the type, with eg:
use db = dbSchema.GetDataContext()
db.DataContext.ExecuteCommand(sqlCreateTableStmt a b c)
My upload process goes through lists of lists and functions calling functions. And I don't know what the pros and cons are of where to declare use db. It could be re-done locally in each function, or "globally" outside any module, or in the first, top-level function and passed along from function to function as a parameter. Or some combination.
Hopefully that's enough of a question to be worthwhile. Right now I have a use declaration in each function. Not passing it ever. In some places one function declares use db and calls another function that declares use db again. I don't know if there's overhead in making or managing these connections. Or whatever else to worry about.
Thanks in advance.
I have an ABAP class method, say, select_something. select_something has an exporting parameter, say, et_result. et_result is of type standard table because the type of et_result cannot be determined until runtime.
The method sometimes gives a short dump saying With ABAP/4 Open SQL array select, the output table is too small at "select * into table et_result from (lv_tablename) where..."
Error analysis:
......in this particular case, the database table is 3806 bytes wide, but the internal table is only 70 bytes wide.
I tried "any table" too and the error is the same.
You could return a data reference. Your query will no longer fail, and you can assign the data to a correctly typed field symbol afterwards.
" Definition
class-methods select_all
importing
!tabname type string
returning
value(results) type ref to data.
...
...
" Implementation
method select_all.
data dref type ref to data.
create data dref type standard table of (tabname).
field-symbols <tab> type any table.
assign dref->* to <tab>.
select * from (tabname) into table <tab>.
get reference of <tab> into results.
endmethod.
Also, I agree with #vwegert that dynamic queries (and programming for that matter) should be avoided when possible.
What you're trying to do looks horribly wrong on many levels. NEVER use SELECT FROM (whatever) unless someone points a gun at your head AND the door is locked tight. You'll loose every kind of static error checking the system might be able to provide you with. For example, the compiler will no longer be able to tell you "Hey, that table you're reading from is 3806 bytes wide." It simply can't tell, even if you use constants. You'll find that out the hard way, producing short dumps, especially when switching between unicode and NUC systems, quite likely some in production systems. No fun.
(Actually there are a few - very very VERY few - good uses for dynamic table names in the SELECT statement. I need them about once every two to three years, and I code quite a lot weird stuff. Just avoid them wherever you can, even at the cost of writing more code. It's just not worth the trouble fixing broken stuff later.)
Then, changing the generic formal parameter type does not do anything to the type of the actual parameter. If you pass a STANRDARD TABLE OF mandt WITH DEFAULT KEY to your method, that table will have lines of 3 characters. It will be a STANDARD TABLE, and as such, it will also be an ANY TABLE, and that's about it. You can twist the generic types anywhere you like, there's no way to enforce correctness using generic types the way you use them. It's up to the caller to make sure that all the right types are used. That's a bad way to fly.
First off, I agree with vwegert's response, try to avoid dynamic sql selections if you can
That said, check the short dump. If the error is an exception class, you can wrap the SELECT statement in a try/catch block and at least stop it from dumping.
You can also try "INTO CORRESPONDING FIELDS OF TABLE et_result". If ET_RESULT is dynamic, you might have to cast it into the proper structure using RTTS. This might give you some ideas...
Couldn't agree more to vwegert, but if there is absolutely no other way (and there usually is) of performing your task than using dynamic select statements and dynamically typed parameters, do some checks on the type of the table and the parameter at runtime.
Use CL_ABAP_TYPEDESCR and its subclasses to do so.
This way, you can handle errors at runtime without your program dumping,
But as vwegert said, this dynamic stuff is pure evil and will most certainly break at some point during runtime. Adding the necessary error handling will most likely be a lot more work and a lot harder than redesigning your code to none dynamic SQL and typed parameters
I found this question, which is similar to a problem that I would like to solve:
How to manage multiple tables with the same structure
However, due to the craptastical nature of VB, the solution doesn't really work. It specifically doesn't work because VB.NET requires the implementation of each method/property in the interface to be explicitly declared.
As for the problem that I'm really trying to solve, here it is:
I have many lookup/domain tables in the database that all have the same structure
The items in these tables are typically used for drop downs in the interface
I would like to avoid a bunch of boilerplate repository methods to retrieve the contents of these tables (one method per table really sucks when you have 40 tables)
I am not using the One True Lookup Table anti-pattern and this is not an option
Does anyone have another solution for this that work work in VB?
Generic Repository should work in this case. There are many available online or you can write a simpler one for just the lookup tables.
Here is the code that we ended up using:
Public Function GetDomainTableList(tableName As String) As IEnumerable(Of Object)
Dim table = CType(GetType(FECEntities).GetProperty(tableName).GetValue(DB, Nothing), IEnumerable(Of Object))
Dim dt = From r In table
Select r
Return dt.ToList()
End Function
I had originally thought that this wouldn't work for us since I was trying to project each object returned into a DomainTableItem class that I had written. But then I realized that the SelectList constructor didn't really care about the type of object that it takes in. You just pass in a String containing the property name and it uses reflection to pull out the value.
So everything works out peachy this way and I avoided writing one method per domain/lookup table.
I've inherited some code that has a Public Module for data access:
Code looks like:
Public Module Foo
Dim ds As New DataSet
Public Function GetDataSet(ByVal sqlQuery As String) As DataSet
...
Fill(ds)...
...
return ds
End Function
End Module
And all the pages call GetDataSet(sql). Am I correct is assuming that this is a bad idea? Worst case is that concurrent callers could get each others data?
Your concerns about concurrent callers is well founded. The solution is to just move the "Dim ds.." from the module into the GetDataSet routine. Then its local, on the stack, and theres no chance of stepping on each other.
A larger problem is that composing SQL queries as string in client code is not good application design, it can be OK for SQL utilities, but nothing else. This approach will keep you from using Linq to SQL, Linq to Entities, Stored Procedures, most of the more desirable DB-access security models and probably exposes you to SQL Injection attacks.
Very bad. With that architecture there is absolutely no way to use a parameterized query or stored procedure to protect yourself from SQL Injection...and that's just a start.
You're also going to be missing out on any kind of strongly typed data sets (which make life a whole lot easier).
i use something similar to this and have never had any problems. makes data access sooo easy. i don't mind writing SQL and in fact it kind of helps me understand exactly what data i'm getting. so long as data access is clearly separated (ie, you pull data consistently from the same location), and you sanitize all data in the SQL string, i don't see anything wrong w/this. i do agree that public variable is bad, though.
sigh... or maybe i'm a bad programmer :\ let the downvoting begin...