score:2
The solution you're looking for is to require entities have an IsDeleted
value of false
:
modelBuilder.Entity<Company>()
.Map( emc => emc.Requires( "IsDeleted" ).HasValue( false ) );
Now only companies with IsDeleted == false
will be retrieved from the DB
Update from comment:
modelBuilder.Entity<Company>()
.Map( emc =>
{
emc.MapInheritedProperties();
emc.Requires( "IsDeleted" ).HasValue( false );
} )
.Ignore( c => c.IsDeleted );
Update: test code which was successful (helper methods found here):
[Table("EntityA")]
public partial class EntityA
{
public int EntityAId { get; set; }
public string Description { get; set; }
public virtual EntityB PrimaryEntityB { get; set; }
public virtual EntityB AlternativeEntityB { get; set; }
public bool IsDeleted { get; set; }
}
[Table("EntityB")]
public partial class EntityB
{
public int EntityBId { get; set; }
public string Description { get; set; }
[InverseProperty("PrimaryEntityB")]
public virtual ICollection<EntityA> EntityAsViaPrimary { get; set; }
[InverseProperty( "AlternativeEntityB" )]
public virtual ICollection<EntityA> EntityAsViaAlternative { get; set; }
}
public partial class TestEntities : DbContext
{
public TestEntities()
: base("TestEntities")
{
Database.SetInitializer( new DatabaseInitializer() );
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EntityA>()
.Map( emc =>
{
emc.Requires( "IsDeleted" ).HasValue( false );
} )
.Ignore( a => a.IsDeleted );
}
public override int SaveChanges()
{
foreach( var entry in this.ChangeTracker.Entries<EntityA>() )
{
if( entry.State == EntityState.Deleted )
{
SoftDelete( entry );
}
}
return base.SaveChanges();
}
private void SoftDelete( DbEntityEntry entry )
{
var entityType = entry.Entity.GetType();
var tableName = GetTableName( entityType );
var pkName = GetPrimaryKeyName( entityType );
var deleteSql = string.Format( "update {0} set IsDeleted = 1 where {1} = @id",
tableName,
pkName );
Database.ExecuteSqlCommand( deleteSql, new SqlParameter( "@id", entry.OriginalValues[ pkName ] ) );
entry.State = EntityState.Detached;
}
private string GetPrimaryKeyName( Type type )
{
return GetEntitySet( type ).ElementType.KeyMembers[ 0 ].Name;
}
private string GetTableName( Type type )
{
EntitySetBase es = GetEntitySet( type );
return string.Format( "[{0}].[{1}]",
es.MetadataProperties[ "Schema" ].Value,
es.MetadataProperties[ "Table" ].Value );
}
private EntitySetBase GetEntitySet( Type type )
{
ObjectContext octx = ( ( IObjectContextAdapter )this ).ObjectContext;
string typeName = ObjectContext.GetObjectType( type ).Name;
var es = octx.MetadataWorkspace
.GetItemCollection( DataSpace.SSpace )
.GetItems<EntityContainer>()
.SelectMany( c => c.BaseEntitySets
.Where( e => e.Name == typeName ) )
.FirstOrDefault();
if( es == null )
throw new ArgumentException( "Entity type not found in GetTableName", typeName );
return es;
}
public DbSet<EntityA> EntityAs { get; set; }
public DbSet<EntityB> EntityBs { get; set; }
}
Application code:
class Program
{
static void Main(string[] args)
{
using( var db = new TestEntities() )
{
var a0 = new EntityA()
{
EntityAId = 1,
Description = "hi"
};
var a1 = new EntityA()
{
EntityAId = 2,
Description = "bye"
};
db.EntityAs.Add( a0 );
db.EntityAs.Add( a1 );
var b = new EntityB()
{
EntityBId = 1,
Description = "Big B"
};
a1.PrimaryEntityB = b;
db.SaveChanges();
// this prints "1"
Console.WriteLine( b.EntityAsViaPrimary.Count() );
db.EntityAs.Remove( a1 );
db.SaveChanges();
// this prints "0"
Console.WriteLine( b.EntityAsViaPrimary.Count() );
}
var input = Console.ReadLine();
}
}
score:0
You can do soft delete like this:
- In OnModelCreating add an IsDeleted discriminator to every entity that can be soft deleted
- Override SaveChanges and find all the entries to be deleted
- Run SQL on these entries to set the IsDeleted discriminator then set their state to "detached"
- Change any unique indexes to ignore any soft deleted records
You can find working code at this answer: How to soft delete using Entity Framework Code First
And that code was picked up by this Blog: http://netpl.blogspot.com/2013/10/soft-delete-pattern-for-entity.html
score:0
Four years later, I finally stumbled on a library that does exactly what I want.
EntityFramework.DynamicFilter.
modelBuilder.Filter("IsDeleted", (ISoftDelete d) => d.IsDeleted, false);
The above snippet ensures that the soft-deleted items are not retrieved. This affects both direct queries (db.Set<Foo>().ToList()
) and indirect loadaed entities db.Set<Foo>().Include(e => e.Bars).ToList()
), thus completely hiding the soft deleted entities from view.
For completeness' sake, I've combined this with an override to SaveChanges()
which converts hard deletes to soft deletes before committing to the database.
This means that developers are able to safely use hard delete logic, and they'll never even realize that the context is using soft deletes. They don't need to know, they don't need to care, they can't forget to implement it the right way, they never need to write a check for the IsDeleted
flag.
Source: stackoverflow.com
Related Query
- LINQ Source Code Available
- creating Linq to sqlite dbml from DbLinq source code
- Make access possible to dynamic table LINQ EF6 Code First
- Is it possible to have one LINQ in one line of code for
- How to handle nulls in this LINQ Code using a possible null List?
- source code for LINQ 101 samples
- Include null cells in Linq query from DB in C# code
- c# Linq or code to extract groups from a single list of source data
- Convert string[] to int[] in one line of code using LINQ
- Code equivalent to the 'let' keyword in chained LINQ extension method calls
- EF LINQ include multiple and nested entities
- Linq code to select one item
- FindAsync and Include LINQ statements
- How are people unit testing code that uses Linq to SQL
- LINQ Include vs Join. Are they equivalent?
- Is it possible to handle exceptions within LINQ queries?
- How to select multiple values from a Dictionary using Linq as simple as possible
- C# linq include before-after where
- Is it Possible to call a Stored Procedure using LINQ in LINQPad?
- Where to draw the line - is it possible to love LINQ too much?
- conditional include in linq to entities?
- How is it possible that "RemoveAll" in LINQ is much faster than iteration?
- Is it possible to use Linq to get a total count of items in a list of lists?
- Include nested entities using LINQ
- LINQ query to perform a projection, skipping or wrapping exceptions where source throws on IEnumerable.GetNext()
- Filtering include items in LINQ and Entity Framework
- Is an outer join possible with Linq to Entity Framework
- Why doesn't LINQ include a `distinct` keyword?
- Is it possible to express this code in LINQ?
- EF 6 - Include Why Do I not have linq choice?
More Query from same tag
- Parsing through an XML file using a randomly generated integer
- how to convert ListItemCollection (dropdownlist.items) to a dictionary<string,string>?
- Problem with deserializing the grouped data (json)
- Prints decreased days left with each List of date
- Why is this LINQ not finding an element two levels down?
- Sequence contains no matching element - Return SiteMapNode matching custom attribute using LINQ
- Linq filtering entity's collection ends up in LINQ to Entities casting error
- implement repository in asp.net mvc 5
- Linq2SQL "Local sequence cannot be used in LINQ to SQL" error
- How can I select all subnodes of a node, and not all descendats?
- Checking if a generic IEnumerable is empty
- LINQ query returning null for nested objects in Entity DB
- Select from multiple lists
- VB.NET LINQ Method Syntax disallows implicit conversions from 'Integer?' to 'Integer'
- Difference linq and plinq
- Convert array of employees to Dictionary
- How to emulate case-when for linq?
- Cartesian on NULL arrays
- LINQ Current record and x number of records on either side
- IQueryable<T> does not contain a definition for 'Include' and no extension method 'Include'
- reading xml with linq (c#)
- How to assert something about every item in enumerable in a long LINQ chain
- What's the best way to not join on everything exponentially?
- Lambdaexpression of Linq-query in a variable
- EF LINQ to SQL, dividing by zero error, generated query puts parameters in wrong order
- Linq query to get child records
- EF Core Include On Collection Class Property
- Show Only 10 records in gridview
- EF filtering child collection and grandchild collection
- Select items from a List where the children contain the items from another List using LINQ