How to define what DatabaseGenerated.Computed should compute? - entity-framework-4

I am just doing my first steps with EF CodeFirst, especially with dataAnnotations.
Now I'm doing my best to understand the "DatabaseGenerated" attribute.
What I know so far:
using this attribute gives me three options to handle creation of a property value: Computed, Id and None.
using this attribute means, that the property can not be updated manually - it is done by the database
So - as I can imagine what happens when using th "Id" option, I have no idea what happens when using "Computed" option. I red that this should tell the db to compute the field value.
For example: field "sum" = field "price" + field "shipping".
But how can I use that in that way? I looked around and did not find any examples. Could you please help me?

You can't use EF to tell the database how to compute the column -- you can only tell EF that the column is database generated so it should be retrieved from the database for your use in code.
To control how the database computes the column you have to manually instruct it either outside of EF or in your database initialization logic.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
context.Database.ExecuteSqlCommand("RAW SQL HERE");
}
Your SQL (MS T-SQL) might look like this (more here):
CREATE TABLE t2 (a int, b int, c int, x float,
y AS CASE x
WHEN 0 THEN a
WHEN 1 THEN b
ELSE c
END)
For SQL here's some info about Computed Colums:
http://msdn.microsoft.com/en-us/library/ms191250(v=sql.105).aspx
Also for reference:
http://msdn.microsoft.com/en-us/library/gg193958.aspx

Related

inserting a row having no values for Primary Key columns fails

For the following table:
I run the following stored procedure:
I'm redirected to "Results" tab and seeing nothing. Then if I click on "refresh" icon (below Results tab), then I get the dialog saying:
SQLCODE = -625 validation error for column ID, value "* null *"
And of course, nothing is added...
As far as I understand, firebird expects somevalue for RC_ID (which is my PK and should principally automatically incremented). If I give value also for RC_ID, it is working well.
So, what should I do to make a clear "insert" without these errors?
The problem is that you are not setting a value for the primary key. Contrary to your expectation, primary keys are not automatically incremented. This is the case in any database I'm aware of. You always need to mark it as an identity, auto increment or generated, or something else to get that behavior, although some tools (table builders) may already apply this for you by default.
If you are using Firebird 3, you can define your column as GENERATED BY DEFAULT AS IDENTITY (see Identity Column Type in the Firebird 3 release notes). For earlier Firebird versions the best way is to define a sequence (also known as generator) with a before insert trigger that populates the primary key column.
For more details on how to define an identity column (or define the trigger), see my answer on this question: Easiest way to create an auto increment field in Firebird database.
In firebird, the autoincrement was not working like in MySQL. Thus, sending a value for RC_ID was a must...
I found some working examples based on idea:
create a generator
assign it to column (PK)
call GEN_ID with that generator like this:
:
begin
insert into RESERVATIONCATEGORY (RC_ID, RC_NAAM)
values (
GEN_ID(GEN_RESERVATIONCATEGORY _ID,1), 'selam'
);
suspend;
end

In MVC, how can I retrieve records from database matching a range of string serial numbers that include numbers?

I have an MVC application that uses Code First Entity Framework.
I have records in my database for serial numbers that are strings, and a combination of letters and numbers. The last 4 are always the number part.
I am trying to retrieve all records in between range A and B, so for example from SERIAL-NO-0020 to SERIAL-NO-0050
I cannot convert the string number part to an integer because Linq To Entities doesn't support it. So as an example to get all records with a serial number higher than 20, this doesn't work:
var records = context.SerialNumbers.Where(m => Convert.ToDecimal(m.SerialNo.Substring(10, 4)) > 20).ToList();
Is there a way to do this without first pulling all the records from the database and filtering further?
Convert.ToDecimal can't be translated to SQL when using it with Linq to Entities.
You can create a stored procedure that query the data so you can do anyahting that can't be done by EF.
Another solution is to create a computed column.
First, add a new property. Let name it SerialId in your SerialNumber entity.
Second, Decorate that property with a data annotation:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
or use fluent configuration if you want:
modelBuilder.Entity<SerialNumber>().Property(t => t.SerialId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
Third, Add new EF migration and in the generated migration file, just update it by passing a new value to defaultValueSql parameter liek below:
public override void Up()
{
AddColumn(
"dbo.SerialNumber",
"SerialId",
c => c.Int(nullable: false, defaultValueSql: "CAST(SUBSTRING(SerialNo, 11, 4) AS INT)"));
}
The modification says that each line of SerialNumber table has a generated column and its value is calculated by using this SQL statement => CAST(SUBSTRING(SerialNo, 11, 4) AS INT)
You can update your database by running ef command => update-databse.
Finally, you can change your Linq to Entities like below and you don't need any conversion:
var records = context.SerialNumbers.Where(m => m.SerialId > 20).ToList();
Instead of Writing Queries you can write SP and access this SP (Stored Proceure) with the help of Linq.
In SP you can split the record first and then compare. It will also take less time and increase the performance.

Add Integer Number to existing Values - Neo4j

Using Neo4j.
I would like to add a integer number to values already existing in properties of several relationships that I call this way:
MATCH x=(()-[y]->(s:SOL{PRB:"Taking time"})) SET y.points=+2
But it doesn't add anything, just replace by 2 the value I want to incremente.
To achieve this use
SET y.points = y.points + 2
From your original question it looks like you were trying to use the Addition Assignment operator which exists in lots of languages (e.g. python, type/javascript, C#, etc.). However, in cypher += is a little different and is designed to do this in a way which allows you to add or update properties to or on entire nodes or relationships based on a mapping.
If you had a parameter like the below (copy this into the neo4j browser to create a param).
:param someMapping: {a:1, b:2}
The query below would create a property b on the node with value 2, and set the value of property a on that node to 1.
MATCH (n:SomeLabel) WHERE n.a = 0
SET n+= $someMapping
RETURN n

Recognize the type of the parameters of a user defined sql to be used in a Delphi TQuery at runtime

I'm writing a delphi(7 ver) application and in some place I want to execute parameterized queries (for BDE and Paradox) which will be loaded at runtime into a TQuery by the user. These queries will be stored in text files (one text file for one query). The application then, will construct for any parameter of the query, one input control (Tedit) in order to be able to accept values by the user. Also there will be a button for the execution of query. My question is how can I recognize the datatype of the query's parameter? Is there a way to get this type without of cause to be included in some way in the text file containing the query?
Create a second query from the first, but modify its where clause to ensure no rows.
SELECT * FROM MYTABLE WHERE PKFIELD IS NULL
Name your parameters so that you can establish their datatypes from the fieldtypes of this second query.
I realise this only works for relatively simple cases, but it should get you some of the way.
the advantage of using a parameter is that you don't need to know its data type.
Use the string value from the tedit
"select * from mytable where myfield = :param1"
"parambyname('param1').asstring := edit1.text"
I've made this with MySQL database. you must define some parameters, Exemple:
SELECT * FROM MyTable WHERE MyField=[ANNEE];
in this case, i have an other table, called balise, that look like this
"ID" "BALISE" "CAPTION" "DEFAULT_VALUE" "CNDT" "COMPOSANT"
"1" "ANNEE" "Année" "2014" "Properties.MaxValue=2014||Properties.MinValue=2007" 1;
in runtime, this mean that:
Make in my Panel, a TLablel that have caption Année
Make in the same line an other component type 1 (That mean in my case TcxSpinEdit), this component have défault value 2014, have Two properties Max Value=2014 and Min Value=2007, (I use RTTI to modifie this value of parameters, in Delphi ver7, use TypeInfo).
An Other Button with function called Actualise, this function have Original query, must browse an array of TBalise that i have created, take the value (In my case, take TcxSpinEdit(MyObject).Value), and replace it in the copy of my query (AnsiReplaceStr(Requete, '[ANNEE]', MyValue)), so i have the final query to execute it.
I have module in complete projet, worked with this methode, and it workk fine.

Silverlight / Data Challenging Issue

I'm a little stumped on this one. Anyone have any ideas? I'll try to lay out the example as brief as possible.
Creating Silverlight 3.0 application against SQL 2005 database. Using RIA Services and Entity Framework for data access.
I need to be able to populate a grid against a table. However, my grid UI and my table structure is different. Basically my grid needs to turn rows into columns (like a PIVOT table). Here are my challenges / assumptions
I have no idea until runtime which columns I will have on the grid.
Silverlight 3 only supports binding to properties
Silverlight 3 does not allow you to add a row to the grid and manually populate data.
As we all know, Silverlight does not have the System.Data (mainly DataTable) namespace
So, how do I create an object w/ dynamic properties so that I can bind to the grid. Every idea I've had (multi-dimensional arrays, hash tables, etc.) fall apart b/c SL needs a property to bind to, I can't manually add/fill a data row, and I can't figure out a way to add dynamic properties. I've seen an article on a solution involving a linked list but I'm looking for a better alternative. It may come down to making a special "Cody Grid" which will be a bunch of text boxes/labels. Doable for sure but I'll lose some grid functionality that users expect
The ONLY solution I have been able to come up is to create a PIVOT table query in SQL 2005 and use an entity based on that query/view. SQL 2008 would help me with that. I would prefer to do it in Silverlight but if that is the last resort, so be it. If I go the PIVOT route, how do I implement a changing data structure in Entity Framework?
Data Sample.
Table
Name Date Value
Cody 1/1/09 15
Cody 1/2/09 18
Mike 1/1/09 20
Mike 1/8/09 77
Grid UI should look like
Name 1/1/09 1/2/09 1/3/09 .... 1/8/09
Cody 15 18 NULL NULL
Mike 20 NULL NULL 77
Cody
My team came up with a good solution. I'm not sure who deserves the credit but it's somewhere in google land. So far it works pretty good.
Essentially the solution comes down to using reflection to build a dynamic object based on this dynamic data. The function takes in a 2-dimensional array and turns it into a List
object with properties that can be bound. We put this process in a WCF Service and it seems to do exactly what we need so far.
Here is some of the code that builds the object using Reflection
AppDomain myDomain = AppDomain.CurrentDomain;
AssemblyName myAsmName = new AssemblyName("MyAssembly");
AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run);
ModuleBuilder myModule = myAssembly.DefineDynamicModule(myAsmName.Name);
TypeBuilder myType = myModule.DefineType("DataSource", TypeAttributes.Public);
string columnName = "whatever";
for (int j = 0; j <= array.GetUpperBound(1); j++)
{
Type properyType = typeof(T);
FieldBuilder exField = myType.DefineField("_" + "columnName" + counter, properyType, FieldAttributes.Private);
//The following line is where I’m passing columnName + counter and getting errors with some strings but not others.
PropertyBuilder exProperty = myType.DefineProperty(columnName + counter.ToString(), PropertyAttributes.None, properyType, Type.EmptyTypes);
//Get
MethodBuilder exGetMethod = myType.DefineMethod("get_" + "columnName" + counter, MethodAttributes.Public, properyType, Type.EmptyTypes); ILGenerator getIlgen = exGetMethod.GetILGenerator();
//IL for a simple getter:
//ldarg.0
//ldfld int32 SilverlightClassLibrary1.Class1::_Age
//ret
getIlgen.Emit(OpCodes.Ldarg_0);
getIlgen.Emit(OpCodes.Ldfld, exField);
getIlgen.Emit(OpCodes.Ret);
exProperty.SetGetMethod(exGetMethod);
//Set
MethodBuilder exSetMethod = myType.DefineMethod("set_" + "columnName" + counter, MethodAttributes.Public, null, new Type[] { properyType }); ILGenerator setIlgen = exSetMethod.GetILGenerator();
//IL for a simple setter:
//ldarg.0
//ldarg.1
//stfld int32 SilverlightClassLibrary1.Class1::_Age
//ret
setIlgen.Emit(OpCodes.Ldarg_0);
setIlgen.Emit(OpCodes.Ldarg_1);
setIlgen.Emit(OpCodes.Stfld, exField); setIlgen.Emit(OpCodes.Ret);
exProperty.SetSetMethod(exSetMethod);
counter++;
}
finished = myType.CreateType();
You can dynamically set columns with their associated bindings (ensuring that AutoGenerateColumns is off):
For instance, the name column:
DataGridTextColumn txtColumn = new DataGridTextColumn();
textColumn.Header = "Name";
textColumn.Binding = new Binding("FirstName");
myDataGrid.Columns.Add(txttColumn);
The ObservableCollection you use to store the data that is queried could possibly be overriden to support pivoting, making sure to change the binding of the DataGrid columns, as shown above.
Note: This is a fair amount of hand waving i'm sure (haven't touched silverlight for over a year); but I hope it's enough to formulate another strategy.
if you are working with two dimensional array then adding columns dynamically as shown above will not work.
The problem is with silverlight it cannot understand the binding of columns to a list.
So we have to create list of rows with row convertor that will represent our two dimensional arrays.
this one worked for me
http://www.scottlogic.co.uk/blog/colin/2010/03/binding-a-silverlight-3-datagrid-to-dynamic-data-via-idictionary-updated/

Resources