L2Entities, stored procedure and mapping - asp.net

Finally checked out L2E framework and ran into problems almost instantly.
Yeah, i know... i should read some books before.
Situation:
entity with props -> id and name.
entity is mapped to table, which has id and name columns.
sproc, which returns ONLY id column.
Problem:
ObjectResult<MyProp> result = _container.MyStoredProcedure(uberParameter);
Calling this will cause an error
[guilty method goes here] threw exception:
System.Data.EntityCommandExecutionException: The data reader is incompatible with the specified 'DataBase.MyPropTableObject'. A member of the type, 'name', does not have a corresponding column in the data reader with the same name..
Problem #2:
Can`t "just return" that field, cause that column has XML data type, but sproc uses fancy select statements, which causes:
Msg 421, Level 16, State 1, Line 1
The xml data type cannot be selected as DISTINCT because it is not comparable.
Question:
Is it possible to exclusively turn off mapping for this entity prop only for this one sproc?

Problem 1 is due to the proc not having the columns to populate the entity. You don't really need the proc if you have mapped the table, just select the field you want from it using linq
var result = MyEntities.EntityIMapped.First(r => r.id = uberParameter).Name;
Would give you the value from the Name column of the table for the given id. You don't need to use a stored proc for this.
Problem 2 sounds like it is in the proc, I would think that distinct on an xml data column would give a lot of results, but I'm only guessing as I don't know your solution.
This is not a direct answer for your question but, hopefully it will point you in the right direction.

Related

Find unused labels

Is there any way I can find labels which are not used in D365 FO (labels which dont have references)?
The cross references are stored in database DYNAMICSXREFDB. You can use a sql query to generate a list of labels that have no references.
This query uses two tables in the database:
Names holds an entry for each object in the application that can be referenced.
The Path field of the table holds the name of the object (e.g. /Labels/#FormRunConfiguration:ViewDefaultLabel is the path of the ViewDefaultLabel in the FormRunConfiguration label file.
Field Id is used to reference a record in this table in other tables.
References holds the actual references that connect the objects.
Field SourceId contains the Id of the Names record of the object that references another object identified by field TargetId.
The actual query could look like this:
SELECT LabelObjects.Path AS UnusedLabel
FROM [dbo].[Names] AS LabelObjects
WHERE LabelObjects.Path LIKE '/Labels/%'
AND NOT EXISTS
(SELECT *
FROM [dbo].[References] AS LabelReferences
WHERE LabelReferences.TargetId = LabelObjects.Id)
Make sure to compile the application to update the cross reference data. Otherwise the query might give you wrong results. When I run this query on a version 10.0.3 PU27 environment, it returns one standard label as a result.

Using Date parameter in SQL query, ASP.net

I am writing a code that calls a column from a dataset using a SQL query. I use two parameters to identify which rows to select. One is the ProductSerialNumber, and the other is a datetimestamp. See my SQL query below
Select TestStation FROM tblData
WHERE ProductSerialNumber = ? AND Datetimestamp = ?
In the dataset's datatable the productserialnumber is formatted as text, and the other is formatted as a date (as you would expect).
In my vb.net code, I grab the Datetimestamp from another source (don't ask why, the only thing you need to know is that it grabs a valid datetimestamp, dimensioned as a date, that matches exactly with the tblData's entry) and I use the premade query to generate a datatable. The query is a Fill query called "TestStationLookUp"
my vb.net code looks like this
Dim dt as new dataset.tbldataDataTable
Dim dta As New DataSetTableAdapters.tbldataTableAdapter
Dim ProductSerialNumber as string = "XXXXXX"
Dim DateTimeStamp as date = SomeDateVariable
dta.TestStationLookUp(dt, ProductSerialNumber, DateTimeStamp)
It is here that the code tells me:
Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
Line 7366: dataTable.Clear
Line 7367: End If
Error: Line 7368: Dim returnValue As Integer = Me.Adapter.Fill(dataTable)
Line 7369: Return returnValue
Line 7370: End Function
I cannot understand why this error arises, as everything is dimensioned the way it should be. This exact code setup works elsewhere in my code (except it doesn't use a date), but this specific piece won't work.
Also, if I go to the dataset in my solution, I can use the "preview data" on this query and type in the EXACT same parameters (the ProductSerialNumber and DateTimeStamp that match the record in the table AND what I use in my vb code) and it will give me produce the table I want.
Can anyone assist?
This error means that you are trying to access not valid unique id "ProductSerialNumber", maybe it does not exist
Failed to enable constraints. One or more rows contain values
violating non-null, unique, or foreign-key constraints.
Instead of passing the variable that comes from dataset ,pass a valid number that you are sure it exists in database

Determine flyway variables from earlier SQL step

I'd like to use flyway for a DB update with the situation that an DB already exists with productive data in it. The problem I'm looking at now (and I did not find a nice solution yet), is the following:
There is an existing DB table with numeric IDs, e.g.
create table objects ( obj_id number, ...)
There is a sequence "obj_seq" to allocate new obj_ids
During my DB migration I need to introduce a few new objects, hence I need new
object IDs. However I do not know at development time, what ID
numbers these will be
There is a DB trigger which later references these IDs. To improve performance I'd like to avoid determine the actual IDs every time the trigger runs but rather put the IDs directly into the trigger
Example (very simplified) of what I have in mind:
insert into objects (obj_id, ...) values (obj_seq.nextval, ...)
select obj_seq.currval from dual
-> store this in variable "newID"
create trigger on some_other_table
when new.id = newID
...
Now, is it possible to dynamically determine/use such variables? I have seen the flyway placeholders but my understanding is that I cannot set them dynamically as in the example above.
I could use a Java-based migration script and do whatever string magic I like - so, that would be a way of doing it, but maybe there is a more elegant way using SQL?
Many thx!!
tge
If the table you are updating contains only reference data, get rid of the sequence and assign the IDs manually.
If it contains a mix of reference and user data, you need to select the id based on values in other columns.

Invalid Column Name : SQL / ASP.NET

I'm having a hard time debugging a particular problem and have a couple questions. First, here is what's going on:
I have a relatively simple table called Employees, which has a primary key / identity Id. There is also a Username column - which is a GUID foreign key to my aspnet_Users table used for membership. Finally, there is another foreign key Team_Id which points to another table, Teams.
All I'm really trying to do is give a selected employee's Id and pass it to a method in the DAL which then finds the employee with the following statement:
var employee = entities.Employees.Where(emp => emp.Id == employeeId);
Once the employee is retrieved, I want to use another value which is passed to the same method - the selected team's Id - to update the employee's Team_Id value (which team they are assigned to), using the following:
employee.First().Team_Id = teamId;
entities.SaveChanges();
I get the exception
Invalid column name: {Name}
which doesn't make sense to me, because Employee doesn't have a name column.
All of that said, my questions are:
Where could the mix up possibly be coming from? I've tried thinking up a way to step through the code, but it seems like the error is somewhere in the query itself so I'm not really sure how to trace the execution of the query itself.
Is it possible that it may have something to do with my generated Entities? I noticed that when I type employee.First(). Name comes up in Intellisense. I'm really confused by that, since as I've mentioned there is no Name column in the employees table.
Fixed the issue. I just removed the existing Entity Framework Model and re-added it.
As far as the query goes, you can always use SQL Profiler to watch what scripts are actually running. That's a good way to troubleshoot generated SQL anyway.
For your property, somehow that did make it to your class, so your data model thinks it's there, for whatever reason. I'd say just go to your data model (you don't mention if this this is EF or LINQ-to-SQL), and you'll see "Name" there. Just remove it, and it will remove it from the class, and from the data access stuff.

Efficiently finding unique values in a database table

I've got a database table with a very large amount of rows. This table represents messages that are logged by a system. Each message has a message type and this is stored it it's own field in the table. I'm writing a website for querying this message log. If I want to search by message type then ideally I would want to have a drop down box listing the message types that have come up in the database. Message types may change over time so I can't hard code the types into the drop down. I'll have to do some sort of lookup. Iterating over the entire table contents to find unique message values is obviously very stupid however being stupid in the database field I'm here asking for a better way. Perhaps a separate lookup table which the database occasionally updates listing just the unique message types that I can populate my drop down from would be a better idea.
Any suggestions would be much appreciated.
The platform I'm using is ASP.NET MVC and SQL Server 2005
A separate lookup table with the id of the message type stored in your log. This will reduce the size and increase the efficiency of the log. Also it would Normalize your data.
Yep, I would definitely go with the separate lookup table. You can then populate it using something like:
INSERT TypeLookup (Type)
SELECT DISTINCT Type
FROM BigMassiveTable
You could then run a top-up job periodically to pull in new types from your main table that don't already exist in the lookup table.
SELECT DISTINCT message_type
FROM message_log
is the most straightforward but not very efficient way.
If you have a list of types that can possibly appear in the log, use this:
SELECT message_type
FROM message_types mt
WHERE message_type IN
(
SELECT message_type
FROM message_log
)
This will be more efficient if message_log.message_type is indexed.
If you don't have this table but want to create one, and message_log.message_type is indexed, use a recursive CTE to emulate loose index scan:
WITH rows (message_type) AS
(
SELECT MIN(message_type) AS mm
FROM message_log
UNION ALL
SELECT message_type
FROM (
SELECT mn.message_type, ROW_NUMBER() OVER (ORDER BY mn.message_type) AS rn
FROM rows r
JOIN message_type mn
ON mn.message_type > r.message_type
WHERE r.message_type IS NOT NULL
) q
WHERE rn = 1
)
SELECT message_type
FROM rows r
OPTION (MAXRECURSION 0)
I just wanted to state the obvious: normalize the data.
message_types
message_type | message_type_name
messages
message_id | message_type | message_type_name
Then you can just do without any cached DISTINCT:
For your dropdown
SELECT * FROM message_types
For your retrieval
SELECT * FROM messages WHERE message_type = ?
SELECT m.*, mt.message_type_name FROM messages AS m
JOIN message_types AS mt
ON ( m.message_type = mt.message_type)
I'm not sure why you would want a cached DISTINCT which you'll have to update, when you can slightly tweak the schema and have one with RI.
Create an index on the message type:
CREATE INDEX IX_Messages_MessageType ON Messages (MessageType)
Then to get a list of unique Message Types, you run:
SELECT DISTINCT MessageType
FROM Messages
ORDER BY MessageType
Because the index is physically sorted in order of MessageType SQL Server can very quickly, and efficiently, scan through the index, picking up a list of unique message types.
It is not bad performing - it's what SQL Server is good at.
Admittedly, you can save some space by having a "message types" table. And if you only display a few messages at a time: then the bookmark lookup, as it joins back to the MessageTypes table, won't be a problem. But if you start displaying hundreds or thousands of messages at a time, then the join back to MessageTypes can get pretty expensive, and needless, and it will be faster to have the MessageType stored with the message.
But i would have no problem with creating an index on the MessageType column, and selecting distinct. SQL Server loves that sort of thing. But if you're finding it to be a real load on your server, once you're getting dozens of hits a second, then follow the other suggestion and cache them in memory.
My personal solution would be:
create the index
select distinct
and if i still had problems
cache in memory that expires after 30 seconds
As for the normalized/denormalized issue. Normalizing saves space, at the cost of CPU when joins are constantly performed. But the logical point of denoralization is to avoid duplicate data, which can lead to inconsistent data.
Are you planning on changing the text of a message type, which if you stored with the messages you would have to update all rows?
Or is there something to be said for the fact that at the time of the message the message type was "Client response requested"?
Have you considered an indexed view? Its result set is materialized and persists in storage so that the overhead of the lookup is separated from the rest of whatever you're trying to do.
SQL Server takes care of automagically updating the view when there is a data change which in its opinion would change the contents of the view, so in this respect it's less flexible than Oracle materialized.
The MessageType should be a Foreign Key in the main table to a definition table containing the message type codes and descriptions. This will greatly increase your lookup performance.
Something like
DECLARE #MessageTypes TABLE(
MessageTypeCode VARCHAR(10),
MessageTypeDesciption VARCHAR(100)
)
DECLARE #Messages TABLE(
MessageTypeCode VARCHAR(10),
MessageValue VARCHAR(MAX),
MessageLogDate DATETIME,
AdditionalNotes VARCHAR(MAX)
)
From this design, your lookup should only query MessageTypes
As others have said, create a separate table of message types. When you add a record to the message table, check if the message type already exists in the table. If not, add it. In either case, then post the identifier from the message type table into the message table. This should give you normalized data. Yes, it's a little extra time when you add a record, but should be more efficient on retrieval.
If there are a lot more adds then reads and if the "message type" is short, an entirely different approach would be to still create the separate message type table, but don't reference it when doing adds, and only update it lazily, on demand.
Namely, (a) Include a time-stamp in each message record. (b) Keep a list of the message types found as of the last time you checked. (c) Each time you check, search for any new message types added since the last time, as in:
create table temp_new_types as
(select distinct message_type
from message
where timestamp>last_type_check
);
insert into message_type_list (message_type)
select message_type
from temp_new_types
where message_type not in (select message_type from message_type_list);
drop table temp_new_types;
Then store the timestamp of this check somewhere so you can use it the next time around.
The answer is to use 'DISTINCT' and each best solution is different for different sizes of table. Thousands of rows, millions, billions ? more ? This are very different best solutions.

Resources