I am using VS2010 and C#
When I map/select my database tables with LINQ to SQL I have to option to change the "member" propery, but when i delete the table (because I changed something in the schema for example) and add it again the member value gets "reset". Is it possible to set/override this member programmaticly, so that I dont have to change it by hand everytime
I mean the member option of
'<'Table Name="dbo.table1" Member="table1">
All L2S ORM classes are partial, so you should be able to encapsulate the table in another property by extending the DataContext class e.g.
public partial class MyDataContext
{
public IEnumerable<Entity> Table
{
get { return DatabaseTable; }
}
}
So in the above scenario you would make your DatabaseTable private and expose it through a another property. You may still need to change that particular piece of code manually if you change the name of your table, but it means you are only changing it once and don't have to change it everytime you reference the table somewhere in your code.
Related
I've done some searches (over the web and SO) but so far have been unable to find something that directly answer this:
Is there anyway to force L2S to use a Stored Procedure when acessing a Database?
This is different from simply using SPROC's with L2S: The thing is, I'm relying on LINQ to lazy load elements by accessing then through the generated "Child Property". If I use a SPROC to retrieve the elements of one table, map then to an entity in LINQ, and then access a child property, I believe that LINQ will retrieve the register from the DB using dynamic sql, which goes against my purpose.
UPDATE:
Sorry if the text above isn't clear. What I really want is something that is like the "Default Methods" for Update, Insert and Delete, however, to Select. I want every access to be done through a SPROC, but I want to use Child Property.
Just so you don't think I'm crazy, the thing is that my DAL is build using child properties and I was accessing the database through L2S using dynamic SQL, but last week the client has told me that all database access must be done through SPROCS.
i don't believe that there is a switch or setting that out of the box and automagically would map to using t sprocs the way you are describing. But there is now reason why you couldn't alter the generated DBML file to do what you want. If I had two related tables, a Catalog table and CatalogItem tables, the Linq2SQL generator will naturally give me a property of CatalogItems on Catalog, code like:
private EntitySet<shelf_myndr_Previews_CatalogItem> _shelf_myndr_Previews_CatalogItems;
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="CatalogItem", Storage="_CatalogItems", ThisKey="Id", OtherKey="CatalogId")]
public EntitySet<CatalogItem> CatalogItems
{
get
{
return this._CatalogItems;
//replace this line with a sproc call that ultimately
//returns the expected type
}
set
{
this._CatalogItems.Assign(value);
//replace this line with a sproc call that ultimately
//does a save operation
}
}
There is nothing stopping you from changing that code to be sproc calls there. It'd be some effort for larger applications and I'd be sure that you be getting the benefit from it that you think you would.
How about loading the child entities using the partial OnLoaded() method in the parent entity? That would allow you to avoid messing with generated code. Of course it would no longer be a lazy load, but it's a simple way to do it.
For example:
public partial class Supplier
{
public List<Product> Products { get; set; }
partial void OnLoaded()
{
// GetProductsBySupplierId is the SP dragged into your dbml designer
Products = dataContext.GetProductsBySupplierId(this.Id).ToList();
}
}
Call your stored procedure this way:
Where GetProductsByCategoryName is the name of your stored procedure.
http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx
If I have a LINQ to SQL table that has a field called say Alias.
There is then a method stub called OnAliasChanging(string value);
What I want to do is to grab the value, check the database whether the value already exists and then set the value to the already entered value.
So I may be changing my alias from "griegs" to "slappy" and if slappy exists then I want to revert to the already existing value of "griegs".
So I have;
partial void OnaliasChanging(string value)
{
string prevValue = this.alias;
this.Changed = true;
}
When I check the value of prevValue it's always null.
How can I get the current value of a field?
Update
If I implement something like;
partial void OnaliasChanging(string value)
{
if (this.alias != null)
this.alias = "TEST VALUE";
}
it goes into an infinte loop which is unhealthy.
If I include a check to see whether alias already == "TEST VALUE" the infinate loop still remains as the value is always the original value.
Is there a way to do this?
The code snippets you've posted don't lend themselves to any plausible explanation of why you'd end up with an infinite loop. I'm thinking that this.alias might be a property, as opposed to a field as the character casing would imply, but would need to see more. If it is a property, then you are invoking the OnAliasChanging method before the property is ever set; therefore, trying to set it again in the same method will always cause an infinite loop. Normally the way to design this scenario is to either implement a Cancel property in your OnXyzChanging EventArgs derivative, or save the old value in the OnXyzChanging method and subsequently perform the check/rollback in the OnXyzChanged method if you can't use the first (better) option.
Fundamentally, though, what you're trying to do is not very good design in general and goes against the principles of Linq to SQL specifically. A Linq to SQL entity is supposed to be a POCO with no awareness of sibling entities or the underlying database at all. To perform a dupe-check on every property change not only requires access to the DataContext or SqlConnection, but also causes what could technically be called a side-effect (opening up a new database connection and/or silently discarding the property change). This kind of design just screams for mysterious crashes down the road.
In fact, your particular scenario is one of the main reasons why the DataContext class was made extensible in the first place. This type of operation belongs in there. Let's say that the entity here is called User with table Users.
partial class MyDataContext
{
public bool ChangeAlias(Guid userID, string newAlias)
{
User userToChange = Users.FirstOrDefault(u => u.ID == userID);
if ((userToChange == null) || Users.Any(u => u.Alias == newAlias))
{
return false;
}
userToChange.Alias = newAlias;
// Optional - remove if consumer will make additional changes
SubmitChanges();
return true;
}
}
This encapsulates the operation you want to perform, but doesn't prevent consumers from changing the Alias property directly. If you can live with this, I would stop right there - you should still have a UNIQUE constraint in your database itself, so this method can simply be documented and used as a safe way to attempt a name-change without risking a constraint violation later on (although there is always some risk - you can still have a race condition unless you put this all into a transaction or stored procedure).
If you absolutely must limit access to the underlying property, one way to do this is to hide the original property and make a read-only wrapper. In the Linq designer, click on the Alias property, and on the property sheet, change the Access to Internal and the Name to AliasInternal (but don't touch the Source!). Finally, create a partial class for the entity (I would do this in the same file as the MyDataContext partial class) and write a read-only wrapper for the property:
partial class User
{
public string Alias
{
get { return AliasInternal; }
}
}
You'll also have to update the Alias references in our ChangeAlias method to AliasInternal.
Be aware that this may break queries that try to filter/group on the new Alias wrapper (I believe Linq will complain that it can't find a SQL mapping). The property itself will work fine as an accessor, but if you need to perform lookups on the Alias then you will likely need another GetUserByAlias helper method in MyDataContext, one which can perform the "real" query on AliasInternal.
Things start to get a little dicey when you decide you want to mess with the data-access logic of Linq in addition to the domain logic, which is why I recommend above that you just leave the Alias property alone and document its usage appropriately. Linq is designed around optimistic concurrency; typically when you need to enforce a UNIQUE constraint in your application, you wait until the changes are actually saved and then handle the constraint violation if it happens. If you want to do it immediately your task becomes harder, which is the reason for this verbosity and general kludginess.
One more time - I'm recommending against the additional step of creating the read-only wrapper; I've put up some code anyway in case your spec requires it for some reason.
Is it getting hung up because OnaliasChanging is firing during initialization, so your backing field (alias) never gets initialized so it is always null?
Without more context, that's what it sounds like to me.
I feel like this should be easy, but I don't see any way to do it.
I'm using ASP.NET Dynamic Data with Linq to SQL. I've got a table with an Association to the Technician table. The Parent Property is TechAssignment, and on the web form I'm using a DynamicField to display it.
This works fine really, it correctly sees it as a ForeignKeyField and uses that template to give me a dropdown with a list of techs from the Technicians table.
The only problem is that it gives me a list of ALL the technicians, when there are quite a few who are inactive. How can I tell Dynamic Data to filter out inactive technicians so they can't be selected?
LINQ to SQL generates partial classes.
Add a new property (copy from the other foreign key property)
Apply the filter in the get (either by LINQ2SQL or filtering the original property)
Bind to that property
Example UnapprovedContacts in Association table
public partial class Association
{
public IList<Contact> UnapprovedContacts
{
get
{
return Contacts.Where(c => !c.IsApproved).ToList();
}
}
}
I have a L2S generated class called Accounts, I have a L2S class called UsersInAccounts I need to add a function call AddUserToAccount(accountid, userid) should/could this function be added to the partial Accounts class I have created or are partial classes used for getting data rather than editing data
public partial class Account
{
public void addUser(Guid userid)
{
// code
}
}
I don't think that what you are doing is a problem. In your code, you'd probably have an Account instance that you want to do things with so being able to do this:
Account theAccountIWant = GetTheAccount();
theAccountIWant.addUser(myUsersGUID);
...seems pretty intuitive. It might be an idea to do some error trapping inside your addUser method and pass back some sort of success status but that's another discussion.
edit: As advised, if you then retrieve a User object and want to attach it to the Account using the AccountUsers property then this is no use unless you pass the DataContext in.
Can I use partial classes to create properties that points to an association property generated by the L2S designer. Also, will I be able to use the new property in queries?
How can I achieve this?
If you just want to give a different name to the association property, just use the Property page for the association and rename the parent and/or child property. That will change the name of the EntityRef/EntitySet in the class.
EDIT: The downside of using a separate property in a partial class is that LINQ won't be able to use it when generating queries -- essentially you'll be forced to always get the entities before you can use the related properties on the object. By renaming you allow LINQ to use the related properties in constructing the query which can result in a more efficient query. For example, if you want to get entities where a related entity has a particular property value, using the attribute decorated entity will allow LINQ to generate the SQL to pull just those matching values from the database. With the naive property implementation (that simply references the underlying relation property, in effect renaming it), you will be forced to first get all entities, then do the filtering in your application.
Yes you can, but you have to apply the same attributes as the linq2sql generated property i.e.
[Association(Name="Test_TestData", Storage="_TestDatas", ThisKey="SomeId", OtherKey="OtherId")]
public System.Data.Linq.EntitySet<TestData> MyTestDatas
{
get
{
return this.TestDatas;
}
}
TestDatas being the original relation.
Update: A sample query I ran:
var context = new DataClasses1DataContext();
var tests =
from d in context.Tests
where d.MyTestDatas.Any(md=>md.MyId == 2)
select new
{
SomeId = d.SomeId,
SomeData = d.SomeData,
Tests = d.MyTestDatas
};
foreach (var test in tests)
{
var data = test.Tests.ToList();
}