Cant update table from text using linq2sql - c#

Using linq2sql I'm trying to take the string in txtOilChange and update the oilChange integer in the car table of the white fusion.
I know my code below is wrong but what do I need to change?
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
var o = (from c in db.cars
where c.carDesc == "White Fusion"
select c).First();
txtOilChange.Text = o.oilChange.ToString();
db.SubmitChanges();
}

If you're trying to update the record it looks like the assignment statement is reversed.
This:
txtOilChange.Text = o.oilChange.ToString();
Should be:
o.oilChange = int.Parse(txtOilChange.Text);
For better error handling consider using the TryParse method:
int oilChangeValue;
if (int.TryParse(txtOilChange.Text, out oilChangeValue))
{
o.oilChange = oilChangeValue;
db.SubmitChanges();
}
else
{
// invalid value
}

Related

My first try at converting from LINQ to SQL to LINQ to Entity

The program does some very simple lookups to generate data for a flashcard program which supports Mandarin Chinese and English
I deleted the .dbml file and created a Linq to Entities instead.
The original lookup was this:
using (var ceDictionary = new CeDictDataContext(Properties.Settings.Default.ChineseStudyConnection))
{
var definitions = from ed in ceDictionary.CeDicts
where ed.Char == WorkTraditional.Text
where ed.Bopo == foundBo[0]
select ed;
try
{
foreach (var definition in definitions)
{
textDefinition.Text = definition.English;
break;
}
}
catch (System.Data.StrongTypingException eng)
{
Status.Text = eng.Message;
textDefinition.Text = #"DBNull";
}
}
After a bit of head scratching and documentation browsing, I decided I only need to update the using statement and change the 'select ed' to a 'select new'
Like this:
using (var ceDictionary = new ChineseStudyEntities())
{
var definitions = from ed in ceDictionary.CeDicts
where ed.Char == WorkTraditional.Text
where ed.Bopo == foundBo[0]
select new
{
ed.English
};
try
{
foreach (var definition in definitions)
{
textDefinition.Text = definition.English;
break;
}
}
catch (System.Data.StrongTypingException eng)
{
Status.Text = eng.Message;
textDefinition.Text = #"DBNull";
}
}
The good news is: the compiler was happy and the project builds without errors.
The bad news is: the foreach statement crashes at runtime with this (unintelligible to me) error message: Message=LINQ to Entities does not recognize the method 'System.String get_Item(Int32)' method, and this method cannot be translated into a store expression.
It is unintelligible because the one column I'm pulling out of the database is a string and I cannot begin to guess why "get_Item(Int32)" is somehow involved. (The two columns in the 'where' clauses are also strings.)
I think that your problem is with this part: foundBo[0]. Accessing letters by index cannot be translated to common SQL.
Try using Substring instead:
var definitions = from ed in ceDictionary.CeDicts
where ed.Char == WorkTraditional.Text
where ed.Bopo == foundBo.Substring(0, 1)
select ed;
LINQ to SQL cant translate expressionfoundBo[0] to SQL, copy it to variable:
var temp = foundBo[0];
var definitions = from ed in ceDictionary.CeDicts
where ed.Char == WorkTraditional.Text
where ed.Bopo == temp
select ed;

How can I edit or add to a particular field without pull the all object

How I can do just this ( a.myFavorits.Add()) without pulling the all object to var a , because a has a lot of data, and I don't want to pull all a object, but I can't find a way do do it.
I want to do the lambada and the linq without return something but linq is always return something
public static void addFavorits(long f,long idUser)
{
using (var db = dataBase())
{
// here i pull object user from users table
var a = db.users.Where(c => c.id == idUser).SingleOrDefault();
// here i adding to the object field myFavorits new value
//myFavorits is also a table of entitys that connected to user object
a.myFavorits.Add(new BE.FavoritsUsersLong { myLong = f });
db.SaveChanges();
}
}
I thought to do something like this but i dont know how to set the field users_TableId that is the key that connect the 2 tables
public static void addFavorits(long favoritId,long idUser)
{
using (var db = dataBase())
{
db.favoritsUsersLong.Add(new BE.FavoritsUsersLong {myLong = favoritId}
/*,users_TableId =idUser*/);
db.SaveChanges();
}
}
Here's a concrete example that does what you want. In this example, only the Name of a Company is modified and saved. Or an item is added to one of its collections.
var cmp = new Company{ CmpId = 1, Name = "Cmp1" }; // CmpId is the primary key
db.Companies.Attach(cmp);
db.Entry(cmp).Property(c => c.Name).IsModified = true;
// Or add an entity to a collection:
cmp.Users = new[] {new User { Name = "a1", PassWord = "a1" } };
try
{
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}
finally
{
db.Configuration.ValidateOnSaveEnabled = true;
}
Result in SQL:
DECLARE #0 VarChar(30) = 'Cmp1'
DECLARE #1 Int = 1
UPDATE [dbo].[Company]
SET [Name] = #0
WHERE ([CmpId] = #1)
There are a few things to note here:
Obviously you need to know the Id of the entity you want to modify.
The object you create is called a stub entity, which is an incomplete entity. When you try to save such an entity, EF is very likely to complain about null values in required properties. That's why almost certain you'd have to disable validation (temporarily, or, better, dispose the context immediately).
If you want to add an item to a collection, you should leave validation enabled, because you'd want to know for sure that the new entity is valid. So you shouldn't mix these two ways to use a stub entity.
If you often need roughly the same small part of your entity you may consider table splitting.
I'm guessing this is what you want? I don't see you 'editting' I only see you adding.
using (var db = dataBase())
{
var a = new user();
....
//set properties etc..
...
a.myFavorits.Add(new BE.FavoritsUsersLong { myLong = f });
db.users.Add(a);
db.SaveChanges();
}

Linq To SQL Select Dynamic Columns

Is it possible to dynamically limit the number of columns returned from a LINQ to SQL query?
I have a database SQL View with over 50 columns. My app has a domain object with over 50 properties, one for each column. In my winforms project I bind a list of domain objects to a grid. By default only a few of the columns are visible however the user can turn on/off any of the columns.
Users are complaining the grid takes too long to load. I captured the LINQ generated SQL query then executed it within SQL Server Management Studio and verified its slow. If I alter the SQL statement, removing all the invisible columns, it runs almost instantly. There is a direct correlation between performance and the number of columns in the query.
I'm wondering if its possible to dynamically alter the number of columns returned from the LINQ generated SQL query? For example, here is what my code currently looks like:
public List<Entity> GetEntities()
{
using (var context = new CensusEntities())
{
return (from e in context.Entities
select e).ToList();
}
}
The context.Entities object was generated from a SQL View that contains over 50 columns so when the above executes it generates SQL like "SELECT Col1, Col2, Col3, ... Col50 FROM Entity INNER JOIN...". I would like to change the method signature to look like this:
public List<Entity> GetEntities(string[] visibleColumns)
{
using (var context = new CensusEntities())
{
return (from e in context.Entities
select e).ToList();
}
}
I'm not sure how to alter the body of this method to change the generated SQL statement to only return the column values I care about, all others can be NULL.
Something like this should work:
List<string> columns = new List<string>();
columns.Add("EmployeeID");
columns.Add("HireDate");
columns.Add("City");
Add columns to your list ^.
var result = Class.ReturnList(columns);
Pass the List to a method ^.
public static List<Entity> ReturnList(List<string> VisibleColumns)
{
StringBuilder SqlStatement = new StringBuilder();
SqlStatement.Append("Select ");
for (int i = 0; i < VisibleColumns.Count; i++)
{
if (i == VisibleColumns.Count - 1)
{
SqlStatement.Append(VisibleColumns[i]);
}
else
{
SqlStatement.Append(VisibleColumns[i]);
SqlStatement.Append(",");
}
}
SqlStatement.Append(" FROM Entity");
using (var ctx = new DataClasses1DataContext())
{
var result = ctx.ExecuteQuery<Entity>(SqlStatement.ToString());
return result.ToList();
}
}
This basically just makes a SELECT statement with all the fields you passed in with the VisibleColumns list.
In this case, the SQL statement that will be generated by the strings in the VisibleColumns list is:
Select EmployeeID, HireDate, City From Employee
(note: i used the Northwind database to try this out, hence the EmployeeID etc column names. You should replace them with your own, obviously.)
It is not trivial to do this dynamically, but if you have a limited set of combinations of columns you want to retreive you can do an explicit select like this:
public List<Entity> GetEntities()
{
using (var context = new CensusEntities())
{
return (from e in context.Entities
select new
{
col1 = e.col1,
col4 = e.col4,
col5 = e.col5,
}
).ToList()
.Select(x=>new Entity{col1 = x.col1, col4 = x.col4, col5 = x.col5}).ToList();
}
}
The extra select step is necessary because LINQ2SQL won't create partial entities for you.
Create a method for each common combination of columns (especially the initial) the users wants to retrieve.
However to make this dynamic you can build a query with you entity stored as a property in an anonymous class and collect your result properties in another anonymous class in second property in the same anonymous class. Finally you select your entities from the collected objects into objects of the correct type.
public List<Entity> GetEntities()
{
using (var context = new CensusEntities())
{
var combinedResult = (from e in context.Entities
select new {
Entity = e,
CollectedValues = new
{
// Insert default values of the correct type as placeholders
col1 = 0, // or "" for string or false for bool
col2 = 0, // or "" for string or false for bool
// ...
col49 = 0, // or "" for string or false for bool
col50 = 0, // or "" for string or false for bool
}
);
// Then copy each requested property
// col1
if (useCol1)
{
var combinedResult = (from e in combinedResult
select new {
Entity = e,
CollectedValues = new
{
col1 = e.Enitity.col1, // <-- here we update with the real value
col2 = e.CollectedValues.col2, // <-- here we just use any previous value
// ...
col49 = e.CollectedValues.col49, // <-- here we just use any previous value
col50 = e.CollectedValues.col50, // <-- here we just use any previous value }
);
}
// col2
if (useCol2)
{
// same as last time
col1 = e.CollectedValues.col1, // <-- here we just use any previous value
col2 = e.Enitity.col2, // <-- here we update with the real value
// ...
}
// repeat for all columns, update the column you want to fetch
// Just get the collected objects, discard the temporary
// Entity property. When the query is executed here only
// The properties we actually have used from the Entity object
// will be fetched from the database and mapped.
return combinedResult.Select(x => x.CollectedValues).ToList()
.Select(x=>new Entity{col1 = x.col1, col2 = x.col2, ... col50 = x.col50}).ToList();
}
}
There will be lots of code, and a pain to maintain, but it should work.
If you are going this route I suggest that you build a code generator that builds this code with reflection from your LINQ context.
Try something like this
using (var context = new CensusEntities())
{
var q = from e in context.Entities
select e.myfield1,e.myfield2;
return q.Tolist();
}
The resulting query should be lighter and also all the data conversion that goes underneath.
But if you really need to build dynamic input, I think some dynamic sql should be involved. So
build the dynamic SQL and get a data table
use a datatable to a dynamic object conversion as shown here
How can I convert a DataTable into a Dynamic object?
BTW a lot of hard work, I think you should considered using the first block of code.

updating a list of records with linq-to-sql

I have a table that has 2 columns: FruitID, FruitSize. I want to write a query that takes in a list of FruitIDs and a FruitSize and that sets the new FruitSize for all the fruits.
This is what I have so far:
public void ChangeFruitSizes(List<long> TheFruitIDs, long NewFruitSize)
{
using (SomeDC MyDC = new SomeDC())
{
var TheFruits = (from f in MyDC.Fruits
where TheFruitIDs.Contains(f.FruitID)
select f).ToList();
foreach (Fruits f in TheFruits)
{
f.FruitSize = NewFruitSize;
}
MyDC.SubmitChanges();
}
}
It's currently not bugging but the fields in the database aren't updated. Thanks for your suggestions.
To write this in more concise way, you can try ForEach() in list like below:
using (SomeDC MyDC = new SomeDC())
{
(from f in MyDC.Fruits
where TheFruitIDs.Contains(f.FruitID)
select f).ToList().ForEach(F => F.FruitSize = NewFruitSize);
MyDC.SubmitChanges();
}
Just looking at the code everything is correct. Probably the error is at what is not shown: The model. I suspect you don't have a primary key defined. Define a primary key on the ID field and re-create the model (remove the table from the designer and add it back).

How to get text from LINQ2SQL query?

I have a web page in which I am giving USER the options of writing notes. Now when ever the web page checks that a USER is:abc then it pulls up the note from the MEMO Table.
Here is my code in Page_Load():
using (EntityMemoDataContext em = new EntityMemoDataContext())
{
int getEntity = Int16.Parse(Session["EntityIdSelected"].ToString());
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity
select r.Memo;
tbShowNote.Text = String.Join(#"<br />", showMemo);
}
tbShowNote is showing me value like this:
test<br />test1<br />test1<br />test4<br />test4
And I want it like this:
Test
Test1
Test2 ...
tbShowNote is a TextBox!
You only asked for the first memo, so that's what you got back. If you want it enumerated with each one on it's own line in html, you could do this:
using (EntityMemoDataContext em = new EntityMemoDataContext())
{
int getEntity1 = Int16.Parse(Session["EntityIdSelected"].ToString());
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity1
select new
{
r.Memo
};
tbShowNote.Text = String.Join(#"<br />", showMemo);
}
The key takeaway is if r.Memo is of type string, then the LINQ query you executed gave you back a IQueryable<string>. It's on you to decide if you want to flatten that list later.
Edit: Equiso made a good observation in that you're actually returning an IQueryable of an anonymous type, not IQueryable<string> due to the new { ... } syntax. I'd say combine his answer with mine and run with it:
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity1
select r.Memo;
tbShowNote.Text = String.Join(#"<br />", showMemo);
The problem is in the select part of your linq query, you are wrapping your results in an anonymous type, that is why when you call ToString() you see { Memo = test }. You probably want it like this:
var showMemo = from r in em.EntityMemoVs_1s
where r.EntityID == getEntity1
select r.Memo;
After that showMemo will contain just strings.
It looks like your showMemo is a collection and you are then just assigning the top value? If you are putting them in one string then you need to aggregate them together.

Categories

Resources