Insert row to any table with LINQ - c#

I want to develop a dynamic insert method with LINQ.
Let's assume I have two tables like:
Product
{
id int,
name varchar(20),
price int
}
Factory
{
id int,
name varchar(50),
address varchar(240)
}
But, consider that I don't know the tables, but only the names of them.
This is how I get the column names of the table which I know the name of:
var db = new DataContext();
var columnNames = db.Mapping.MappingSource
.GetModel(typeof(DataContext))
.GetMetaType(typeof(table_name))
.DataMembers;
But I can't figure out how to get the column names of the table which I don't know the name of. What I tried so far:
context.Mapping.GetTables().FirstOrDefault(
x=> x.TableName == table_name ).Model.ContextType.Attributes;
table_name is dynamically changes and be like: Product, Factory etc.. But this way is a dead end, I think.
So, in the end I couldn't figure out how to get column names of a random table, let alone inserting a row to random table.
I can do this with classic way using SqlCommands but I want to know how to do it with LINQ.

As Mant101 said in his comment:
I don't think Linq is going to help here. You could write some code in
ADO.NET to get the columns definitions from the database, then use
some reflection to build an insert/update statement based on the
properties of the object that match the columns. I would ask why you
need to do this, are you working with some database that is in an
unknown state when the app run?
And as StriplingWarrior gives countenance to him with:
Mant101 is right: The whole purpose of an object-relational mapper is
to make it easier to work with persisted data by converting it into
objects that you can use in the programming language. Since you're not
going to program against those objects in this case, you don't get any
value from LINQ-to-SQL. You're better off bypassing the ORM and using
straight SQL/ADO.NET.
Inserting any table using generic methods with LINQ seems impossible.
However, you can do it with SQL.

Related

Insert data manually in a safe way?

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.

How To can Select**DB Table

If I have a database in each table where the ID field and its appropriate function in any field do not take the administrator behavior so that tables and field contents can be fetched until the serial number is unified without duplicate values
Appropriate in this context using except.
Is there a code that can fetch tables either in sql or in the Entity Framework ؟
Eexcept_Admin_except_List
List<int> tempIdList = answeripE.Select(q => q.ID).ToList();
var quslist = db.Qustion.Where(q => !tempIdList.Contains(q.ID));
\Thanks for the creator of "daryal" Get All Except from SQL database using Entity Framework
I need to do this without asking for each table and querying it. And also request SQL from the database as a whole without exception such as
select*
IDfield
FROM
MSDB_Table T
WHERE
T.id == MaxBy(T.OrderBy(x => x.id);
can replace "where TABLE1.id 'OR' Table2.id" decode all the tables and give a result.
All I'm looking forward to is that I can query one database on a whole, get it on a list without the use of tables or a composite key because it serves me in analyzing a set of data converted to other data formats, for example when representing a database in the form of JSON There are a lot of them on more than one platform and in a single database and to avoid the repetition of the data I need to do this or a comprehensive query may be compared or to investigate or like Solver Tool in Excel, so far did not get the answer to show me the first step is because it does not exist originally or because it is not possible?
If you want Entity Framework to retrieve all columns except a subset of them, the best way to do that is either via a stored procedure or a view. With a view you can query it using LINQ and add your predicates in code, but in a stored procedure you will have to write it and feed your predicate conditions into it...so it sounds like a view would be better for you.
Old example, but should guide you through the process:
https://www.mssqltips.com/sqlservertip/1990/how-to-use-sql-server-views-with-the-entity-framework/

Find all table's name in one Query or SQL command

I would like to find all table's names in my T-SQL command. My command can be a Select, Update, Delete, Insert, Merge or Truncate.
I can use C#. But I don't really how can I find them because there is a lot of possibility.
For example: I can have a select like select below:
SELECT
<Schemaname>.<TableName1>.Field1,
<TableName2>.Field2,
Field3,
Field4 = ( Select .. FROM <TableName6> WHERE ... )
FROM
<TableName1> , <TableName2>
INNER JOIN
<TableName3> AS TableName4 ON .....
WHERE ....
<TableName2>.Field3 in ( SELECT ... FROM TableName5 )
The list that I am looking should has these table's names
TableName1,TableName2,TableName3,TableName5,TableName6
TableName4 is an alias name in this case and it does not present a real name of a table in database.
I have the command where I have used a table name with schema name and an other table without schema name and also I have the alias for some of my tables and the alias can be like a table name that I have really in my database.
Doing this purely with t-sql is incredibly difficult. And by difficult I mean nearly impossible. It will take days and days to get a t-sql script that even comes close to being accurate for this. There are just too many possibilities. Unless the table name you are looking for is so unique you would feel comfortable just searching your code for that table name. Anything else is only going to get you close. Good luck!!!
This is impossible to get 100% correct and exhaustive. What happens if you have a function? And that function pulls data from a view? And that view pulls from other tables?
And even in your example above there are SO many possibilities. You would be better off creating this as a stored procedure and then looking at sys.depends.
But even that isn't exhaustive as it only goes as deep as this query, not the other objects dependencies being referenced
Not too sure I really understand what you are trying to achieve but here are my 2 cents:
Assuming that you can extract the SQL command using some code (can't help if you need THAT code) from your many SSIS packages.
Based on that, I would
use a reference list of all the database objects and search for each of them through your SQLCommand (extracted from your SSIS package)
Build a list of the all the name strings found (list of objects,
could be tables, views, functions, stored procedures)
Then use that list to find the dependent objects in your DB (if you
need to go that deep)
select DISTINCT s1.class_desc, s1.object_id, referenced_major_id, OBJECT_NAME(s1.object_id) AS ObjName , OBJECT_NAME(s2.object_id) AS ObjName2
from sys.sql_dependencies s1
INNER JOIN sys.objects s2 ON s2.object_id = s1.referenced_major_id
Put all that into your result table
Move on to next SSIS package
Would that work for you?
B

How to get the primary key from a table without making a second trip?

How would I get the primary key ID number from a Table without making a second trip to the database in LINQ To SQL?
Right now, I submit the data to a table, and make another trip to figure out what id was assigned to the new field (in an auto increment id field). I want to do this in LINQ To SQL and not in Raw SQL (I no longer use Raw SQL).
Also, second part of my question is: I am always careful to know the ID of a user that's online because I'd rather call their information in various tables using their ID as opposed to using a GUID or a username, which are all long strings. I do this because I think that SQL Server doing a numeric compare is much (?) more efficient than doing a username (string) or even a guid (very long string) compare. My questions is, am I more concerned than I should be? Is the difference worth always keeping the userid (int32) in say, session state?
#RedFilter provided some interesting/promising leads for the first question, because I am at this stage unable to try them, if anyone knows or can confirm these changes that he recommended in the comments section of his answer?
If you have a reference to the object, you can just use that reference and call the primary key after you call db.SubmitChanges(). The LINQ object will automatically update its (Identifier) primary key field to reflect the new one assigned to it via SQL Server.
Example (vb.net):
Dim db As New NorthwindDataContext
Dim prod As New Product
prod.ProductName = "cheese!"
db.Products.InsertOnSubmit(prod)
db.SubmitChanges()
MessageBox.Show(prod.ProductID)
You could probably include the above code in a function and return the ProductID (or equivalent primary key) and use it somewhere else.
EDIT: If you are not doing atomic updates, you could add each new product to a separate Collection and iterate through it after you call SubmitChanges. I wish LINQ provided a 'database sneak peek' like a dataset would.
Unless you are doing something out of the ordinary, you should not need to do anything extra to retrieve the primary key that is generated.
When you call SubmitChanges on your Linq-to-SQL datacontext, it automatically updates the primary key values for your objects.
Regarding your second question - there may be a small performance improvement by doing a scan on a numeric field as opposed to something like varchar() but you will see much better performance either way by ensuring that you have the correct columns in your database indexed. And, with SQL Server if you create a primary key using an identity column, it will by default have a clustered index over it.
Linq to SQL automatically sets the identity value of your class with the ID generated when you insert a new record. Just access the property. I don't know if it uses a separate query for this or not, having never used it, but it is not unusual for ORMs to require another query to get back the last inserted ID.
Two ways you can do this independent of Linq To SQL (that may work with it):
1) If you are using SQL Server 2005 or higher, you can use the OUTPUT clause:
Returns information from, or
expressions based on, each row
affected by an INSERT, UPDATE, or
DELETE statement. These results can be
returned to the processing application
for use in such things as confirmation
messages, archiving, and other such
application requirements.
Alternatively, results can be inserted
into a table or table variable.
2) Alternately, you can construct a batch INSERT statement like this:
insert into MyTable
(field1)
values
('xxx');
select scope_identity();
which works at least as far back as SQL Server 2000.
In T-SQL, you could use the OUTPUT clause, saying:
INSERT table (columns...)
OUTPUT inserted.ID
SELECT columns...
So if you can configure LINQ to use that construct for doing inserts, then you can probably get it back easily. But whether LINQ can get a value back from an insert, I'll let someone else answer that.
Calling a stored procedure from LINQ that returns the ID as an output parameter is probably the easiest approach.

How to read the result of SELECT * from joined tables with duplicate column names in .NET

I am a PHP/MySQL developer, slowly venturing into the realm of C#/SQL Server and I am having a problem in C# when it comes to reading an SQL Server query that joins two tables.
Given the two tables:
TableA:
int:id
VARCHAR(50):name
int:b_id
TableB:
int:id
VARCHAR(50):name
And given the query
SELECT * FROM TableA,TableB WHERE TableA.b_id = TableB.id;
Now in C# I normally read query data in the following fashion:
SqlDataReader data_reader= sql_command.ExecuteReader();
data_reader["Field"];
Except in this case I need to differentiate from TableA's name column, and TableB's name column.
In PHP I would simply ask for the field "TableA.name" or "TableB.name" accordingly but when I try something like
data_reader["TableB.name"];
in C#, my code errors out.
How can fix this? And how can I read a query on multiple tables in C#?
The result set only sees the returned data/column names, not the underlying table. Change your query to something like
SELECT TableA.Name as Name_TA, TableB.Name as Name_TB from ...
Then you can refer to the fields like this:
data_reader["Name_TA"];
To those posting that it is wrong to use "SELECT *", I strongly disagree with you. There are many real world cases where a SELECT * is necessary. Your absolute statements about its "wrong" use may be leading someone astray from what is a legitimate solution.
The problem here does not lie with the use of SELECT *, but with a constraint in ADO.NET.
As the OP points out, in PHP you can index a data row via the "TABLE.COLUMN" syntax, which is also how raw SQL handles column name conflicts:
SELECT table1.ID, table2.ID FROM table1, table;
Why DataReader is not implemented this way I do not know...
That said, a solution to be used could build your SQL statement dynamically by:
querying the schema of the tables you're selecting from
build your SELECT clause by iterating through the column names in the schema
In this way you could build a query like the following without having to know what columns currently exist in the schema for the tables you're selecting from
SELECT TableA.Name as Name_TA, TableB.Name as Name_TB from ...
You could try reading the values by index (a number) rather than by key.
name = data_reader[4];
You will have to experiment to see how the numbers correspond.
Welcome to the real world. In the real world, we don't use "SELECT *". Specify which columns you want, from which tables, and with which alias, if required.
Although it is better to use a column list to remove duplicate columns, if for any reason you want *****, then just use
rdr.item("duplicate_column_name")
This will return the first column value, since the inner join will have the same values in both identical columns, so this will accomplish the task.
Ideally, you should never have duplicate column names, across a database schema. So if you can rename your schema to not have conflicting names.
That rule is for this very situation. Once you've done your join, it is just a new recordset, and generally the table names do go with it.

Categories