1

有没有简单的方法将属性添加到 Linq to Sql 生成的实体以引用其 DataContext?例如:

var myContext = new DataContext(); 
var product = context.Products.Where(p => p.Id == productId).SingleOrDefault(); 

并且产品实体有一个名为“Context”(product.Context) 的属性,它引用了 myContext,datacontext。

我知道如何自定义生成的实体。我的问题是如何自定义(我认为是 DataContext)来设置它为自己创建的每个实例的“上下文”属性。

我不确定我是否做对了。我想用更少的代码编写一个性能最好的业务封装模型。当我四处搜索时,我发现 DataContext 对象非常轻量级,我认为这是向每个对象添加 DataContext 实例的好方法。这将减少每次我想更新或删除对象时,再次将分离的对象附加到新的数据上下文实例的需要。

如果您有任何其他解决方案,我将不胜感激。

谢谢

4

6 回答 6

2

有没有一种简单的方法可以将属性添加到 Linq to Sql 生成的实体以引用其 DataContext?

没有简单的方法可以实现这一点。

于 2009-01-13T17:56:54.217 回答
1

请参阅此处:确定 Linq to Sql 查询的源 DataContext

我或多或少地问了同样的问题。您可以从 linq to sql 查询返回的 IQueryable 获取上下文,但据我所知,不能从实体本身获取。

于 2009-01-13T19:36:37.167 回答
1

这样做会破坏 LINQ-to-SQL 的部分目的。目的之一是允许您使用您拥有的对象,而不必根据数据库考虑更改您的设计。

在将 DataContext 附加到数据库时,您将代码中的表示与持久化它的方法相结合,这通常是一个糟糕的设计理念。

如果您觉得必须这样做,您始终可以从该类派生,然后在该类上实现一个接口,该接口公开 DataContext。

我建议实现该接口,因为您无法向 LINQ-to-SQL 设计器指示基类,并且您希望所有实体都具有共享实现。

于 2009-01-13T18:02:27.000 回答
0

Actually, I agree to casperOne. If you really have to need this, I remembered that the classes that linq-to-sql generates are partial. So you can write a partial class to any class you want and add extended functionalities to it.

于 2009-01-13T19:17:33.773 回答
0

这是我为 System.Data.Linq 制作的自定义包装器。它包含一个 find 方法,所以不是你的代码:

var myContext = new DataContext(); 
var product = context.Products.Where(p => p.Id == productId).SingleOrDefault();

你可以这样做

var myContext = new DataContext(); 
var product = context.Products.Find(productId); //(assuming productId is your primary key)

您可以获取下面的代码并进行任何您希望设置 product.Context 的自定义修改,但这是修改 DataContext 的示例。

我还做了保存和删除方法。你会注意到我出去重新抓取记录,即使它正在被传递。我这样做是因为记录可能会与上下文分离并且不会更新。如果有人想要完整的代码,我可以发布 github 链接。

public abstract class DbContext : IDisposable
{
    #region Properties
    private string _connectionString { get; set; }
    private DataContext _context { get; set; }
    #endregion

    #region Constructor
    public DbContext(string connectionString)
    {
        _connectionString = connectionString;
        _context = new DataContext(_connectionString);
        Initialized(_context);
    }

    public DbContext(string server, string database, string userID, string password)
    {
        _connectionString = string.Format(
        "Server={0};Database={1};User Id={2};Password={3};MultipleActiveResultSets=true",
        server,
        database,
        userID,
        password);

        _context = new DataContext(_connectionString);
        Initialized(_context);
    }
    #endregion

    #region Methods
    /// <summary>
    /// Is used to get the contents of a Sql Server Table.
    /// </summary>
    /// <typeparam name="TEntity">Type</typeparam>
    /// <returns>Table</returns>
    public Table<TEntity> GetTable<TEntity, TPKType>()
        where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
        where TPKType : struct
    {
        return _context.GetTable<TEntity>();
    }

    /// <summary>
    /// Is used to get the contents of a Sql Server Table.
    /// </summary>
    /// <typeparam name="TEntity">Type</typeparam>
    /// <returns>Table</returns>
    public Table<TEntity> GetTable<TEntity>()
        where TEntity : DbTableEquatable<IDbTableEquatable<long>>
    {
        return GetTable<TEntity, long>();
    }

    protected virtual void Initialized(DataContext context) { }

    /// <summary>
    /// Saves the changes to the database.  In order to save the table must inherit from DbTableEquatable 
    /// and be a type of IDbTableEquatable and the Primary Key Type must be a C# Structure
    /// </summary>
    /// <typeparam name="TEntity">Record Type</typeparam>
    /// <typeparam name="TPKType">Primary Key Type</typeparam>
    /// <param name="entity">Record</param>
    public virtual void SaveChanges<TEntity, TPKType>(TEntity entity)
        where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
        where TPKType : struct
    {
        var changedList = _context.GetTable<TEntity>();
        var ID = entity.GetType().GetProperty("ID").GetValue(entity);

        _preprocessSave<TEntity, TPKType>(entity);

        // Save changes
        if (Convert.ToInt64(ID) == 0)
        {
            // Insert
            // If No ID we need to insert on submit
            _context.GetTable<TEntity>().InsertOnSubmit((TEntity)entity);
            _context.SubmitChanges();
        }
        else
        {
            // Update
            var item = changedList.Where(w => w.Equals(entity)).FirstOrDefault();
            ReflectionManager.SetValuesWithSkip(entity, item, "ID");
            _context.SubmitChanges();
        }

        Refresh();
    }

    /// <summary>
    /// Saves the changes to the database.  In order to save the Table the Record is from must inherit from DbTableEquatable 
    /// and be a type of IDbTableEquatable and the Primary Key Type must be a C# Structure
    /// </summary>
    /// <typeparam name="TEntity">Record Type</typeparam>
    /// <param name="entity">Record</param>
    public virtual void SaveChanges<TEntity>(TEntity entity)
        where TEntity : DbTableEquatable<IDbTableEquatable<long>>
    {
        SaveChanges<TEntity, long>(entity);
    }

    /// <summary>
    /// Saves any non committed changes to the database
    /// </summary>
    public void SaveChanges()
    {
        _context.SubmitChanges();
        Refresh();
    }

    /// <summary>
    /// Marks the record as delete and will be deleted when saved
    /// </summary>
    /// <typeparam name="TEntity">Record Type</typeparam>
    /// <typeparam name="TPKType">Primary Key Type</typeparam>
    /// <param name="entity">Record</param>
    public virtual void DeleteOnSave<TEntity, TPKType>(TEntity entity)
        where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
        where TPKType : struct
    {
        var item = _context.GetTable<TEntity>().Where(w => w.Equals(entity)).FirstOrDefault();
        _context.GetTable<TEntity>().DeleteOnSubmit((TEntity)item);
    }

    /// <summary>
    /// Marks the record as delete and will be deleted when saved
    /// </summary>
    /// <typeparam name="TEntity">Record Type</typeparam>
    /// <param name="entity">Record</param>
    public virtual void DeleteOnSave<TEntity>(TEntity entity)
        where TEntity : DbTableEquatable<IDbTableEquatable<long>>
    {
        DeleteOnSave<TEntity, long>(entity);
    }

    protected virtual void _preprocessSave<TEntity, TPKType>(TEntity entity)
        where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
        where TPKType : struct
    {

    }

    protected virtual void _preprocessSave<TEntity>(TEntity entity)
        where TEntity : DbTableEquatable<IDbTableEquatable<long>>
    {
        _preprocessSave<TEntity, long>(entity);
    }

    public void Dispose()
    {
        _connectionString = "";
        _context.Dispose();
        _context = null;
    }

    public virtual void Refresh<TEntity>(RefreshMode mode, TEntity entity) where TEntity : class
    {
        _context.Refresh(RefreshMode.OverwriteCurrentValues, entity);
    }

    public virtual void Refresh()
    {
        _context = new DataContext(_connectionString);
    }

    public virtual void Refresh<TEntity>(RefreshMode mode, params TEntity[] entities) where TEntity : class
    {
        _context.Refresh(RefreshMode.OverwriteCurrentValues, entities);
    }

    public virtual void Refresh<TEntity>(RefreshMode mode, IEnumerable<TEntity> entities) where TEntity : class
    {
        _context.Refresh(RefreshMode.OverwriteCurrentValues, entities);
    }
    #endregion
}

扩展

public static class Extension
{
    public static TEntity Find<TEntity, TPKType>(this Table<TEntity> table, TPKType ID, string pkName = "ID")
        where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
        where TPKType : struct
    {
        TEntity copy = Activator.CreateInstance<TEntity>();

        // set value through reflection
        copy.GetType().GetProperty(pkName).SetValue(copy, ID, null);
        return (TEntity)table.Where(w => w.Equals(copy)).FirstOrDefault();
    }

    public static TEntity Find<TEntity>(this Table<TEntity> table, long ID, string pkName = "ID")
        where TEntity : DbTableEquatable<IDbTableEquatable<long>>
    {
        TEntity copy = Activator.CreateInstance<TEntity>();

        // set value through reflection
        copy.GetType().GetProperty(pkName).SetValue(copy, ID, null);
        return (TEntity)table.Where(w => w.Equals(copy)).FirstOrDefault();
    }
}

}

接口/抽象

/// <summary>
/// This Class Assumes the type T has a property called ID. MUST be 
/// used with IDbEquatable
/// </summary>
/// <typeparam name="T">Class Type</typeparam>
public abstract class DbTableEquatable<T> : IEquatable<T> where T : class
{
    public bool Equals(T other)
    {
        //Check whether the compared object is null.  
        if (Object.ReferenceEquals(other, null))
        {
            return false;
        }

        //Check whether the compared object references the same data.  
        if (Object.ReferenceEquals(this, other))
        {
            return true;
        }

        return ((dynamic)other).ID == ((dynamic)this).ID;
    }
}

/// <summary>
/// Needs to be inherited from in order for Ion.Data.Linq functions to work
/// </summary>
/// <typeparam name="T">Primary Key Type</typeparam>
public interface IDbTableEquatable<T>
{
    T ID { get; set; }
}

这是一个表实现

[Table(Name = "Crews")]
public class Crew : DbTableEquatable<IDbTableEquatable<long>>, IDbTableEquatable<long>
{
    [Column(IsPrimaryKey = true, DbType = "Bigint NOT NULL IDENTITY", AutoSync = AutoSync.OnInsert, IsDbGenerated = true)]
    public long ID { get; set; }
    [Column]
    public string Alias { get; set; }
    [Column]
    public string DefaultForeground { get; set; }
    [Column]
    public string DefaultBackground { get; set; }
    [Column]
    public string AccountEmailAddress { get; set; }
    [Column]
    public long? CrewLeaderEmployeeID { get; set; }
    [Column]
    public string Comments { get; set; }
    [Column]
    public string Password { get; set; }
    [Column]
    public string PrivateICSLink { get; set; }
    [Column]
    public string PrivateXMLLink { get; set; }
}
于 2014-08-06T19:52:12.450 回答
0

将数据上下文作为 ref 参数传递给部分 Product 对象的自定义方法:

public partial class Product 
{
    public string GetSomethingElse(ref DataContext dbase) 
    {
         return dbase.OtherTableWhatever.Count.ToString(); // whatever
    }
}

在你的 aspx.cs 里面:

var context = new DataContext();
var product = context.Products.SingleOrDefault(x => x.id == 1);
var s = product.GetSomethingElse(ref context);
于 2011-03-09T14:51:42.973 回答