We have a database table that stores the location of some wave files plus related meta data. There is a foreign key (employeeid) on the table that links to an employee table. However not all wav files relate to an employee, for these records employeeid is null. We are using LinqToSQl to access the database, the query to pull out all non employee related wav file records is as follows:
var results = from Wavs in db.WaveFiles
where Wavs.employeeid == null;
Except this returns no records, despite the fact that there are records where employeeid is null. On profiling sql server i discovered the reason no records are returned is because LinqToSQl is turning it into SQL that looks very much like:
SELECT Field1, Field2 //etc
FROM WaveFiles
WHERE 1=0
Obviously this returns no rows. However if I go into the DBML designer and remove the association and save. All of a sudden the exact same LINQ query turns into
SELECT Field1, Field2 //etc
FROM WaveFiles
WHERE EmployeeID IS NULL
I.e. if there is an association then LinqToSql assumes that all records have a value for the foreign key (even though it is nullable and the property appears as a nullable int on the WaveFile entity) and as such deliverately constructs a where clause that will return no records.
Does anyone know if there is a way to keep the association in LinqToSQL but stop this behaviour. A workaround i can think of quickly is to have a calculated field called IsSystemFile and set it to 1 if employeeid is null and 0 otherwise. However this seems like a bit of a hack to work around strange behaviour of LinqToSQl and i would rather do something in the DBML file or define something on the foreign key constraint that will prevent this behaviour.
I think you should double-check your dbml file. Sounds like Linq doesn't know that employeeid is a nullable column. Or look at your .cs file. The attributes for this column should look like this:
[Column(Storage="_employeeid", DbType="Int")]
and not:
[Column(Storage="_employeeid", DbType="Int NOT NULL")]
try this:
var results = from Wavs in db.WaveFiles
where DbNull.Value.Equals(Wavs.employeeid)
another way and good practe a nice is to introduce a default employee where every wave file is associated to, that isnĀ“t associated to a real employee
The column is defined as:
[Column(Storage="_employeeid", DbType="Int")]
The way round it whilst leaving the association was to do a left join from the employee entity collection.
Related
I have a database with many tables. Two of them are like this :
Table A
{
id int,
fkTable int,
fkClass int
}
Table B
{
id int,
reference varchar(100)
}
The A.fkTable field is a foreign key on another table, without particular constrains. We can only know on which table the relation is by B.reference field. The A.fkClass field point to the B.id field.
For example, if B.reference = "Operations", we can determinate that A.fkTable will point to Operations.id. We talk about 20 possibilities for B.reference value.
I know it's possible for Entity Framework to retrieve an specific entity by a field value, but I know only the way by a field in the same table.
Is there a solution in order to avoid manual joining in the code and EF retrieve the good mapped-object in function of B.reference value ? I think I need to declare manually my 20 entities in order to explain to EF the relationship between fkClass and the good table, but i'm not sure how coding the switch case.
And I don't want to do two queries : one in order to get the reference, and another in order to join fkTable to the good entity.
Edit : may can I use HasDiscriminator ?
Edit2 : I can't modify the database. I can only modify my C# project which connects to the database. It's not code-first. It's model-first.
I have a trigger which needs to fill a table with hundreds of rows, I need to type every single insert manually (it is a kind of pre-config table).
This table has an Int FK to an Enum Table. The Enum Table uses an int as a PK and a varchar (which is UNIQUE).
While typing the insert statements I need to be very careful that the integer FK is the correct one.
I would rather like to insert the data by the varchar of the enum.
So I do something like this now:
INSERT INTO MyTable(ColorId)
VALUES(1)
And I would like to do something like this:
INSERT INTO MyTable(ColorStr)
VALUES('Red')
The reason why the Enum has an int PK is because of performance issues (fast queries), but I don't know if it is a good idea now. What do you think?
Is there a safe way to do it? Is it possible to insert data into a Table View?
Sure. Do not insert.
No joke.
First, you do not need to use one insert statement PER LINE - look at the syntax, you can have one insert statement doing a lot of lines.
Second, nothing in the world says you can not do processing (like select and join) on the inserted data.
I generally use table definition like this (with a merge statement) for all my static lookup library data (like country lists). Full automatic maintenance on every change. WIth inserts and updates happening on demand.
When I write C# applications, I use to write sql relations as inner join for example, in the query:
select xxx from TableA as A inner join TableB...
I don't really see why I should define these realtions (hard defined) in Management Studio.
Should I, and why if required?
Regards
Two main reasons and a minor third one: data-integrity and performance - and documentation.
Performance is simple: if you define a relationship between two tables you will normally automatically create an index on those two columns, and your database will use those indexes to speed up look-ups when they can be used.
As for data-integrity, even though you leave the important part of your join out of your example, you assume in a join that a foreign key field can only contain values that exist in the primary key field. Your database can make sure of that, and will make sure of that when you define those relations in SQL server.
If you do not define those relationships, you could easily create a situation where you have, say, Orders, that belong to Customer 12345, who does not exist in your Customer table.
Or you could delete Customer 23456, leaving all their Orders in your system, but without an existing Customer.
A final reason is documentation: your database is not only made to be accessed by your code. If someone else accesses your database and sees only unconnected unrelated tables, how will they know that field cstID in table CstOrderHdr happens to be a reference to field id in table Relations where Relation.RelTyp = 'Customer'? Who is to stop them from filling in 0, null or a random number?
My problem is the following : I map my view to an object through Entity Fluent API. I needed a view containing an few left joins, an there were no unique identifier in the tables, therefore Entity always returned the same set of object. In a few different threads / blogs, I saw a solution consisting of add a column with
ROW_NUMBER() OVER (ORDER BY Id))
I then tried to map it in Entity :
in my class I add a property
public long Row { get; set; }
and in my configuration class I add
HasKey(imc => imc.Row).HasColumnName("Row")
Apparently, the mapping works. What doesn't work is that, when I query the objects with linq, even a Count() will timeout ; however the request itself only returns about 200 lines when used in a SQL Management Studio environement.
Has anyone ever seen this issue ?
EDIT:
I have been able to bypass the problem by replacing the "row_number()" with a newid() in the MS SQL View, but I'm still afraid it might be a problem later on.
Your query is slow which causes the timeout. About 1 million people have seen this before. You would need to analyze the query plan. Computing a row number over the whole table if unindexed can be slow. Also, a row number cannot be used as a key because it's values changes when you change the underlying data. EF does not support changing keys.
If you use newid() as the "key" in the view then you get fresh IDs each time. I think you might not be aware of the fact that a view is merely a shortcut for that particular query. It's contents are not stored anywhere.
Introduce a column that can be used as a key. For example an IDENTITY column.
I just finished using Linq to Sql to map our existing Database structure for use in a Thick Client app.
While writing some Linq Methods to replace some Stored Procedures I noticed that sometimes I could do tblOne.tblTwo.MyDesiredField. I learned that there needed to be an association in the dbml for that to work. Well mine was missing some obvious ones so I added a bunch.
That was when I noticed that sometimes I couldn't do the above as some of the associated tables are considered EntitySets<tblThree> instead of the table, tblThree itself?
To me, there seems to be no rhyme or reason as to what I'll get. Am I doing something wrong in the dbml? Something I need to change in the Properties?
Is this cause for concern? I noticed that to use an EntitySet<tblThree> I need to add an extra from..
from person in context.tblPersons
from address in person.tblAddress where address.AddressType == "Home"
select new {person.Name, address.Home};
EntitySet is a result set. If tableA has a 1 to many relationship with tableB then tableA.tableB refers to the collection of results in tableB that reference the result in tableA.
Table is just the table. If you drag and drop using the designer you'll see that it pluralizes the entitySets which makes things more readable.
EDIT: I imagine from the sounds of your setup, you'll likely see an entitySet as follows
from b in TableA select b.TableB
in this case TableA is a Table, and b.TableB is the EntitySet