SubmitChanges with LINQ to SQL and User Defined Functions - vb.net

On the SQL server I create a UDF. Let's name it fnCompanyDetails. It selects some information about a company from several joint tables.
I then drag-and-drop this function in the new .dbml of my VB project. I want to use it with LINQ. Smth like this:
Dim company = (From c In d.fnCompanyDetails(sap)
Select New With {
.Sap = c.txtSAP,
.CompanyName1 = c.txtCompanyName1, _
.CompanyName2 = c.txtCompanyName2, _
})
The result of this query I display to the user in a form. If some field is changed I want to send the changes to my database, but is this possible if I'm quering like this, from a UDF?
Thank y

No, it is unfortunately not possible to do in a simple way. Linq-to-sql supports reading to custom types, but only support updates through the entity types that exactly corresponds to a table.
Normally the best way is to always read pure entity objects if they are read with the intention to update them.
Another solution is to create entity objects out of the data returned from the udf and then attach those entities to the context. If you attach the entities in their original state first and then make changes after attaching, you should get away without any change tracking problems.

Related

How to import updated records from XML files into SQL Database?

So from last few weeks I was trying to design a SSIS package that would read some XML files that I have and move the data from it to the multiple tables I want.
These file contains different nodes like Individual (parent node) and Address, Alias, Articles (all child nodes of Individual) etc.
Data in those files look like this:
<Individuals>
<Individual>
<UniqueID>1001</UniqueID>
<Name>Ben</Name>
<Soft_Delete>N</Soft_Delete>
<Soft_Delete_Date>NULL</Soft_Delete_Date>
</Individual>
<Addresses>
<Address>
<Address_Line_1>House no 280</Address_Line_1>
<Address_Line_2>NY</Address_Line_2>
<Country>US</Country>
<Soft_Delete>N</Soft_Delete>
<Soft_Delete_Date>NULL</Soft_Delete_Date>
</Address>
<Address>
<Address_Line_1>street 100</Address_Line_1>
<Address_Line_2>California</Address_Line_2>
<Country>US</Country>
<Soft_Delete>N</Soft_Delete>
<Soft_Delete_Date>NULL</Soft_Delete_Date>
</Address>
</Addresses>
</Individuals>
I was successful in designing it and now I have a different task.
The files I had were named like this: Individual_1.xml,Individual_2.xml,Individual_3.xml etc.
Now I have received some new files which are named like this:
Individual_UPDATE_20220716.xml,Individual_UPDATE_20220717.xml,Individual_UPDATE_20220718.xml,Individual_UPDATE_20220720.xml etc
Basically these files contains the updated information of previously inserted records
OR
There are totally new records
For example:
A record or a particular information like Address of an Individual was Soft Deleted.
Now I am wondering how would I design or modify my current SSIS package to update the data from these new files into my database?
Any guidance would be appreciated....
Thank you...
It looks like you have no problem reading the XML so I won't really talk about that. #Yitzack's comment to his prior answer is "a" way to do it. However, his answer assumes you can create staging tables. To do this entirely inside SSIS, the way to do it is as follows...
I would treat all the files the same (as long as they have the same data structure and it seems like the case.
Read the XML as a source.
Proceed to a lookup.
Set the lookup to ignore errors (this is handled in the next step)
Set your lookup to the destination table and lookup uniqueID and add to the data flow. Since you said ignore errors, SSIS will insert a null in that field if the lookup fails to find a match.
Condition Split based on the destination.UniqueID == null and call that output inserts and change the default to updates.
Add a SQL statement to update the existing record and map your row to it (this is somewhat slow and why the merge is better with large data sets).
Connect from Condition Split to update SQL statement and map appropriately.
Add an insert, connect the proper output from Conditional Split and map.
Note: It looks like you are processing from a file system, and it is likely that order is important. You may have to order you foreach loop. I will provide a simple example that you can modify.
Create a filesInOrder variable of type object.
Create a script task.
Add filesInOrder as a read/write variable
Enter script...
var diFiles = new System.IO.DirectoryInfo(#"path to your folder").GetFiles("*.xml");
var files = diFiles.OrderBy(o => o.CreationTime).Select(s => s.FullName);
Dts.Variables["filesInOrder"].Value = files.ToArray();
Make sure you add Using System.Linq; to your code.
Finally, use filesInOrder as your base to a foreach component based on an ADO enumerator (filesInOrder).

How to not get related data in Entity Framework

I have the following scenario.
I have one table in the database A that contains a lot of entries. This table is lightweight and only have a bit of data for each entry.
Another table B has a many to one relationship with A, and can contain lots of data.
I have a client and a server in my application that communicates using WCF.
My problem is that when the client calls a method on the server that should return all the A's, I get much more data than I need to. On the server I basically have a single line of code:
return entityContext.A.ToList();
My problem is that on the client, if I debug and inspect the returned collection, each element has the property B populated with all the data from the expensive table.
I only needed the basic data from the A table to show a list on the client, but ended up sending a ton of data over the wire.
So the question is, how can I make the server ignore the B table when I fetch the data to send to the client. Basically, I need something like the oposite of Include.
You need to turn off lazy loading. It can be done either through designer or in code by calling:
entityContext.ContextOptions.LazyLoadingEnabled = false;

Optimal way to add / update EF entities if added items may or may not already exist

I need some guidance on adding / updating SQL records using EF. Lets say I am writing an application that stores info about files on a hard disk, into an EF4 database. When you press a button, it will scan all the files in a specified path (maybe the whole drive), and store information in the database like the file size, change date etc. Sometimes the file will already be recorded from a previous run, so its properties should be updated; sometimes a batch of files will be detected for the first time and will need to be added.
I am using EF4, and I am seeking the most efficient way of adding new file information and updating existing records. As I understand it, when I press the search button and files are detected, I will have to check for the presence of a file entity, retrieve its ID field, and use that to add or update related information; but if it does not exist already, I will need to create a tree that represents it and its related objects (eg. its folder path), and add that. I will also have to handle the merging of the folder path object as well.
It occurs to me that if there are many millions of files, as there might be on a server, loading the whole database into the context is not ideal or practical. So for every file, I might conceivably have to make a round trip to the database on disk to detect if the entry exists already, retrieve its ID if it exists, then another trip to update. Is there a more efficient way I can insert/update multiple file object trees in one trip to the DB? If there was an Entity context method like 'Insert If It Doesnt Exist And Update If It Does' for example, then I could wrap up multiple in a transaction?
I imagine this would be a fairly common requirement, how is it best done in EF? Any thoughts would be appreciated.(oh my DB is SQLITE if that makes a difference)
You can check if the record already exists in the DB. If not, create and add the record. You can then set the fields of the record which will be common to insert and update like the sample code below.
var strategy_property_in_db = _dbContext.ParameterValues().Where(r => r.Name == strategy_property.Name).FirstOrDefault();
if (strategy_property_in_db == null)
{
strategy_property_in_db = new ParameterValue() { Name = strategy_property.Name };
_dbContext.AddObject("ParameterValues", strategy_property_in_db);
}
strategy_property_in_db.Value = strategy_property.Value;

Check if a given DB object used in Oracle?

Hi does any one know how to check if a given DB object (Table/View/SP/Function) is used inside Oracle.
For example to check if the table "A" is used in any SP/Function or View definitions. I am trying to cleanup unused objects in the database.
I tried the query select * from all_source WHERE TEXT like '%A%' (A is the table name). Do you thing it is safe to assume it is not being used if it does not return any results?
From this ASKTOM question:
You'll have to enable auditing and then come back in 3 months to see.
We don't track this information by default -- also, even with auditing, it may be very
possible to have an object that is INDIRECTLY accessed (eg: via a foreign key for
example) that won't show up.
You can try USER_DEPENDENCIES but that won't tell you about objects referenced by code in
client apps or via dynamic sql
There's code in the thread for checking ALL_SOURCE, but it's highlighted that this isn't a silver bullet.

Table not getting updated while using LinQ

I am trying to update a table using LinQ. Though records are getting inserted, for some reason they are not getting updated.
what can be possible problem
Dim db as new empDataContext
Dim emptable as new employee
if update then
emptable=GetEmp(txtempID.Text)
emptable.Name="Test"
emptable.Age=11
emptable.City="NYC"
else
emptable.Name="Test"
emptable.Age=11
emptable.City="NYC"
emtable.deptID=10
db.employee.InsertOnSubmit(emptable)
end if
db.SubmitChanges()
Judging just from what I can see here, I'm guessing your GetEmp method is using a different data context to retreive the data than the one you're using to save it back to the DB.
When using LINQ to SQL, the context is what tracks the changes to the tables. If you're not careful and mix Contexts by accident, you can get strange behaviors like this.
You can test by chaging:
emptable=GetEmp(txtempID.Text)
to
// Returns the first matching employee with the id
emptable = (from e in db.Employees
where e.id == txtempid.Text).FirstOrDefault()
If you find that the context is the issue, just modify your GetEmp method to accept the context as a parameter rather than creating a new one itself.
What does GetEmp do? In particular, as presented it appears that it does not have a reference to the empDataContext named db. DataContexts are examples of identity maps and as such they track items that have been loaded from a persistence mechanism. If you are using a different DataContext in GetEmp then the DataContext db does not know about the instance of employee with SomeID equal to the value represented by txtempID.Text.
So either pass a reference to db into GetEmp or change your code to the following:
emptable = db.Single(Function(e as employee) e.SomeID=Int32.Parse(txtempID.Text))
then your update should work.
If I had to guess, I would say that the GetEmp() call is not using the same database context object. Therefore, Linq-To-SQL doesn't think any changes are occuring in the "db" database context.
Randy